summaryrefslogtreecommitdiff
path: root/src/android
diff options
context:
space:
mode:
authorJacopo Mondi <jacopo@jmondi.org>2021-06-19 12:10:54 +0200
committerJacopo Mondi <jacopo@jmondi.org>2021-06-23 09:04:15 +0200
commit4bb81dfcc4a7d2134986bb64b733c41388b8060d (patch)
tree9f88225c3110d3eb32e05abfd6047019e1a6cb0d /src/android
parentd7041114d3b00f87a4bf6deb2d1d0c85c61830a0 (diff)
android: Introduce CameraCapabilties class
The camera_device.cpp has grown a little too much, and it has quickly become hard to maintain. Break out the handling of the static information collected at camera initialization time to a new CameraCapabilities class. Break out from the camera_device.cpp file all the functions related to: - Initialization of supported stream configurations - Initialization of static metadata - Initialization of request templates Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> Acked-by: Paul Elder <paul.elder@ideasonboard.com> Tested-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Hirokazu Honda <hiroh@chromium.org>
Diffstat (limited to 'src/android')
-rw-r--r--src/android/camera_capabilities.cpp1164
-rw-r--r--src/android/camera_capabilities.h65
-rw-r--r--src/android/camera_device.cpp1147
-rw-r--r--src/android/camera_device.h27
-rw-r--r--src/android/meson.build1
5 files changed, 1245 insertions, 1159 deletions
diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp
new file mode 100644
index 00000000..00224a6d
--- /dev/null
+++ b/src/android/camera_capabilities.cpp
@@ -0,0 +1,1164 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2021, Google Inc.
+ *
+ * camera_capabilities.cpp - Camera static properties manager
+ */
+
+#include "camera_capabilities.h"
+
+#include <array>
+#include <cmath>
+
+#include <hardware/camera3.h>
+
+#include <libcamera/control_ids.h>
+#include <libcamera/controls.h>
+#include <libcamera/property_ids.h>
+
+#include "libcamera/internal/formats.h"
+#include "libcamera/internal/log.h"
+
+using namespace libcamera;
+
+LOG_DECLARE_CATEGORY(HAL)
+
+namespace {
+
+/*
+ * \var camera3Resolutions
+ * \brief The list of image resolutions defined as mandatory to be supported by
+ * the Android Camera3 specification
+ */
+const std::vector<Size> camera3Resolutions = {
+ { 320, 240 },
+ { 640, 480 },
+ { 1280, 720 },
+ { 1920, 1080 }
+};
+
+/*
+ * \struct Camera3Format
+ * \brief Data associated with an Android format identifier
+ * \var libcameraFormats List of libcamera pixel formats compatible with the
+ * Android format
+ * \var name The human-readable representation of the Android format code
+ */
+struct Camera3Format {
+ std::vector<PixelFormat> libcameraFormats;
+ bool mandatory;
+ const char *name;
+};
+
+/*
+ * \var camera3FormatsMap
+ * \brief Associate Android format code with ancillary data
+ */
+const std::map<int, const Camera3Format> camera3FormatsMap = {
+ {
+ HAL_PIXEL_FORMAT_BLOB, {
+ { formats::MJPEG },
+ true,
+ "BLOB"
+ }
+ }, {
+ HAL_PIXEL_FORMAT_YCbCr_420_888, {
+ { formats::NV12, formats::NV21 },
+ true,
+ "YCbCr_420_888"
+ }
+ }, {
+ /*
+ * \todo Translate IMPLEMENTATION_DEFINED inspecting the gralloc
+ * usage flag. For now, copy the YCbCr_420 configuration.
+ */
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, {
+ { formats::NV12, formats::NV21 },
+ true,
+ "IMPLEMENTATION_DEFINED"
+ }
+ }, {
+ HAL_PIXEL_FORMAT_RAW10, {
+ {
+ formats::SBGGR10_CSI2P,
+ formats::SGBRG10_CSI2P,
+ formats::SGRBG10_CSI2P,
+ formats::SRGGB10_CSI2P
+ },
+ false,
+ "RAW10"
+ }
+ }, {
+ HAL_PIXEL_FORMAT_RAW12, {
+ {
+ formats::SBGGR12_CSI2P,
+ formats::SGBRG12_CSI2P,
+ formats::SGRBG12_CSI2P,
+ formats::SRGGB12_CSI2P
+ },
+ false,
+ "RAW12"
+ }
+ }, {
+ HAL_PIXEL_FORMAT_RAW16, {
+ {
+ formats::SBGGR16,
+ formats::SGBRG16,
+ formats::SGRBG16,
+ formats::SRGGB16
+ },
+ false,
+ "RAW16"
+ }
+ },
+};
+
+} /* namespace */
+
+int CameraCapabilities::initialize(std::shared_ptr<libcamera::Camera> camera,
+ int orientation, int facing)
+{
+ camera_ = camera;
+ orientation_ = orientation;
+ facing_ = facing;
+
+ /* Acquire the camera and initialize available stream configurations. */
+ int ret = camera_->acquire();
+ if (ret) {
+ LOG(HAL, Error) << "Failed to temporarily acquire the camera";
+ return ret;
+ }
+
+ ret = initializeStreamConfigurations();
+ camera_->release();
+ if (ret)
+ return ret;
+
+ return initializeStaticMetadata();
+}
+
+std::vector<Size> CameraCapabilities::getYUVResolutions(CameraConfiguration *cameraConfig,
+ const PixelFormat &pixelFormat,
+ const std::vector<Size> &resolutions)
+{
+ std::vector<Size> supportedResolutions;
+
+ StreamConfiguration &cfg = cameraConfig->at(0);
+ for (const Size &res : resolutions) {
+ cfg.pixelFormat = pixelFormat;
+ cfg.size = res;
+
+ CameraConfiguration::Status status = cameraConfig->validate();
+ if (status != CameraConfiguration::Valid) {
+ LOG(HAL, Debug) << cfg.toString() << " not supported";
+ continue;
+ }
+
+ LOG(HAL, Debug) << cfg.toString() << " supported";
+
+ supportedResolutions.push_back(res);
+ }
+
+ return supportedResolutions;
+}
+
+std::vector<Size> CameraCapabilities::getRawResolutions(const libcamera::PixelFormat &pixelFormat)
+{
+ std::unique_ptr<CameraConfiguration> cameraConfig =
+ camera_->generateConfiguration({ StreamRole::Raw });
+ StreamConfiguration &cfg = cameraConfig->at(0);
+ const StreamFormats &formats = cfg.formats();
+ std::vector<Size> supportedResolutions = formats.sizes(pixelFormat);
+
+ return supportedResolutions;
+}
+
+/*
+ * Initialize the format conversion map to translate from Android format
+ * identifier to libcamera pixel formats and fill in the list of supported
+ * stream configurations to be reported to the Android camera framework through
+ * the camera static metadata.
+ */
+int CameraCapabilities::initializeStreamConfigurations()
+{
+ /*
+ * Get the maximum output resolutions
+ * \todo Get this from the camera properties once defined
+ */
+ std::unique_ptr<CameraConfiguration> cameraConfig =
+ camera_->generateConfiguration({ StillCapture });
+ if (!cameraConfig) {
+ LOG(HAL, Error) << "Failed to get maximum resolution";
+ return -EINVAL;
+ }
+ StreamConfiguration &cfg = cameraConfig->at(0);
+
+ /*
+ * \todo JPEG - Adjust the maximum available resolution by taking the
+ * JPEG encoder requirements into account (alignment and aspect ratio).
+ */
+ const Size maxRes = cfg.size;
+ LOG(HAL, Debug) << "Maximum supported resolution: " << maxRes.toString();
+
+ /*
+ * Build the list of supported image resolutions.
+ *
+ * The resolutions listed in camera3Resolution are mandatory to be
+ * supported, up to the camera maximum resolution.
+ *
+ * Augment the list by adding resolutions calculated from the camera
+ * maximum one.
+ */
+ std::vector<Size> cameraResolutions;
+ std::copy_if(camera3Resolutions.begin(), camera3Resolutions.end(),
+ std::back_inserter(cameraResolutions),
+ [&](const Size &res) { return res < maxRes; });
+
+ /*
+ * The Camera3 specification suggests adding 1/2 and 1/4 of the maximum
+ * resolution.
+ */
+ for (unsigned int divider = 2;; divider <<= 1) {
+ Size derivedSize{
+ maxRes.width / divider,
+ maxRes.height / divider,
+ };
+
+ if (derivedSize.width < 320 ||
+ derivedSize.height < 240)
+ break;
+
+ cameraResolutions.push_back(derivedSize);
+ }
+ cameraResolutions.push_back(maxRes);
+
+ /* Remove duplicated entries from the list of supported resolutions. */
+ std::sort(cameraResolutions.begin(), cameraResolutions.end());
+ auto last = std::unique(cameraResolutions.begin(), cameraResolutions.end());
+ cameraResolutions.erase(last, cameraResolutions.end());
+
+ /*
+ * Build the list of supported camera formats.
+ *
+ * To each Android format a list of compatible libcamera formats is
+ * associated. The first libcamera format that tests successful is added
+ * to the format translation map used when configuring the streams.
+ * It is then tested against the list of supported camera resolutions to
+ * build the stream configuration map reported through the camera static
+ * metadata.
+ */
+ Size maxJpegSize;
+ for (const auto &format : camera3FormatsMap) {
+ int androidFormat = format.first;
+ const Camera3Format &camera3Format = format.second;
+ const std::vector<PixelFormat> &libcameraFormats =
+ camera3Format.libcameraFormats;
+
+ LOG(HAL, Debug) << "Trying to map Android format "
+ << camera3Format.name;
+
+ /*
+ * JPEG is always supported, either produced directly by the
+ * camera, or encoded in the HAL.
+ */
+ if (androidFormat == HAL_PIXEL_FORMAT_BLOB) {
+ formatsMap_[androidFormat] = formats::MJPEG;
+ LOG(HAL, Debug) << "Mapped Android format "
+ << camera3Format.name << " to "
+ << formats::MJPEG.toString()
+ << " (fixed mapping)";
+ continue;
+ }
+
+ /*
+ * Test the libcamera formats that can produce images
+ * compatible with the format defined by Android.
+ */
+ PixelFormat mappedFormat;
+ for (const PixelFormat &pixelFormat : libcameraFormats) {
+
+ LOG(HAL, Debug) << "Testing " << pixelFormat.toString();
+
+ /*
+ * The stream configuration size can be adjusted,
+ * not the pixel format.
+ *
+ * \todo This could be simplified once all pipeline
+ * handlers will report the StreamFormats list of
+ * supported formats.
+ */
+ cfg.pixelFormat = pixelFormat;
+
+ CameraConfiguration::Status status = cameraConfig->validate();
+ if (status != CameraConfiguration::Invalid &&
+ cfg.pixelFormat == pixelFormat) {
+ mappedFormat = pixelFormat;
+ break;
+ }
+ }
+
+ if (!mappedFormat.isValid()) {
+ /* If the format is not mandatory, skip it. */
+ if (!camera3Format.mandatory)
+ continue;
+
+ LOG(HAL, Error)
+ << "Failed to map mandatory Android format "
+ << camera3Format.name << " ("
+ << utils::hex(androidFormat) << "): aborting";
+ return -EINVAL;
+ }
+
+ /*
+ * Record the mapping and then proceed to generate the
+ * stream configurations map, by testing the image resolutions.
+ */
+ formatsMap_[androidFormat] = mappedFormat;
+ LOG(HAL, Debug) << "Mapped Android format "
+ << camera3Format.name << " to "
+ << mappedFormat.toString();
+
+ std::vector<Size> resolutions;
+ const PixelFormatInfo &info = PixelFormatInfo::info(mappedFormat);
+ if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW)
+ resolutions = getRawResolutions(mappedFormat);
+ else
+ resolutions = getYUVResolutions(cameraConfig.get(),
+ mappedFormat,
+ cameraResolutions);
+
+ for (const Size &res : resolutions) {
+ streamConfigurations_.push_back({ res, androidFormat });
+
+ /*
+ * If the format is HAL_PIXEL_FORMAT_YCbCr_420_888
+ * from which JPEG is produced, add an entry for
+ * the JPEG stream.
+ *
+ * \todo Wire the JPEG encoder to query the supported
+ * sizes provided a list of formats it can encode.
+ *
+ * \todo Support JPEG streams produced by the camera
+ * natively.
+ */
+ if (androidFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ streamConfigurations_.push_back(
+ { res, HAL_PIXEL_FORMAT_BLOB });
+ maxJpegSize = std::max(maxJpegSize, res);
+ }
+ }
+
+ /*
+ * \todo Calculate the maximum JPEG buffer size by asking the
+ * encoder giving the maximum frame size required.
+ */
+ maxJpegBufferSize_ = maxJpegSize.width * maxJpegSize.height * 1.5;
+ }
+
+ LOG(HAL, Debug) << "Collected stream configuration map: ";
+ for (const auto &entry : streamConfigurations_)
+ LOG(HAL, Debug) << "{ " << entry.resolution.toString() << " - "
+ << utils::hex(entry.androidFormat) << " }";
+
+ return 0;
+}
+
+int CameraCapabilities::initializeStaticMetadata()
+{
+ staticMetadata_ = std::make_unique<CameraMetadata>(64, 1024);
+ if (!staticMetadata_->isValid()) {
+ LOG(HAL, Error) << "Failed to allocate static metadata";
+ staticMetadata_.reset();
+ return -EINVAL;
+ }
+
+ const ControlInfoMap &controlsInfo = camera_->controls();
+ const ControlList &properties = camera_->properties();
+
+ /* Color correction static metadata. */
+ {
+ std::vector<uint8_t> data;
+ data.reserve(3);
+ const auto &infoMap = controlsInfo.find(&controls::draft::ColorCorrectionAberrationMode);
+ if (infoMap != controlsInfo.end()) {
+ for (const auto &value : infoMap->second.values())
+ data.push_back(value.get<int32_t>());
+ } else {
+ data.push_back(ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF);
+ }
+ staticMetadata_->addEntry(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
+ data);
+ }
+
+ /* Control static metadata. */
+ std::vector<uint8_t> aeAvailableAntiBandingModes = {
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF,
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE_50HZ,
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ,
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO,
+ };
+ staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
+ aeAvailableAntiBandingModes);
+
+ std::vector<uint8_t> aeAvailableModes = {
+ ANDROID_CONTROL_AE_MODE_ON,
+ };
+ staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,
+ aeAvailableModes);
+
+ int64_t minFrameDurationNsec = -1;
+ int64_t maxFrameDurationNsec = -1;
+ const auto frameDurationsInfo = controlsInfo.find(&controls::FrameDurationLimits);
+ if (frameDurationsInfo != controlsInfo.end()) {
+ minFrameDurationNsec = frameDurationsInfo->second.min().get<int64_t>() * 1000;
+ maxFrameDurationNsec = frameDurationsInfo->second.max().get<int64_t>() * 1000;
+
+ /*
+ * Adjust the minimum frame duration to comply with Android
+ * requirements. The camera service mandates all preview/record
+ * streams to have a minimum frame duration < 33,366 milliseconds
+ * (see MAX_PREVIEW_RECORD_DURATION_NS in the camera service
+ * implementation).
+ *
+ * If we're close enough (+ 500 useconds) to that value, round
+ * the minimum frame duration of the camera to an accepted
+ * value.
+ */
+ static constexpr int64_t MAX_PREVIEW_RECORD_DURATION_NS = 1e9 / 29.97;
+ if (minFrameDurationNsec > MAX_PREVIEW_RECORD_DURATION_NS &&
+ minFrameDurationNsec < MAX_PREVIEW_RECORD_DURATION_NS + 500000)
+ minFrameDurationNsec = MAX_PREVIEW_RECORD_DURATION_NS - 1000;
+
+ /*
+ * The AE routine frame rate limits are computed using the frame
+ * duration limits, as libcamera clips the AE routine to the
+ * frame durations.
+ */
+ int32_t maxFps = std::round(1e9 / minFrameDurationNsec);
+ int32_t minFps = std::round(1e9 / maxFrameDurationNsec);
+ minFps = std::max(1, minFps);
+
+ /*
+ * Force rounding errors so that we have the proper frame
+ * durations for when we reuse these variables later
+ */
+ minFrameDurationNsec = 1e9 / maxFps;
+ maxFrameDurationNsec = 1e9 / minFps;
+
+ /*
+ * Register to the camera service {min, max} and {max, max}
+ * intervals as requested by the metadata documentation.
+ */
+ int32_t availableAeFpsTarget[] = {
+ minFps, maxFps, maxFps, maxFps
+ };
+ staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+ availableAeFpsTarget);
+ }
+
+ std::vector<int32_t> aeCompensationRange = {
+ 0, 0,
+ };
+ staticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_RANGE,
+ aeCompensationRange);
+
+ const camera_metadata_rational_t aeCompensationStep[] = {
+ { 0, 1 }
+ };
+ staticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_STEP,
+ aeCompensationStep);
+
+ std::vector<uint8_t> availableAfModes = {
+ ANDROID_CONTROL_AF_MODE_OFF,
+ };
+ staticMetadata_->addEntry(ANDROID_CONTROL_AF_AVAILABLE_MODES,
+ availableAfModes);
+
+ std::vector<uint8_t> availableEffects = {
+ ANDROID_CONTROL_EFFECT_MODE_OFF,
+ };
+ staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_EFFECTS,
+ availableEffects);
+
+ std::vector<uint8_t> availableSceneModes = {
+ ANDROID_CONTROL_SCENE_MODE_DISABLED,
+ };
+ staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
+ availableSceneModes);
+
+ std::vector<uint8_t> availableStabilizationModes = {
+ ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF,
+ };
+ staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
+ availableStabilizationModes);
+
+ /*
+ * \todo Inspect the camera capabilities to report the available
+ * AWB modes. Default to AUTO as CTS tests require it.
+ */
+ std::vector<uint8_t> availableAwbModes = {
+ ANDROID_CONTROL_AWB_MODE_AUTO,
+ };
+ staticMetadata_->addEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES,
+ availableAwbModes);
+
+ std::vector<int32_t> availableMaxRegions = {
+ 0, 0, 0,
+ };
+ staticMetadata_->addEntry(ANDROID_CONTROL_MAX_REGIONS,
+ availableMaxRegions);
+
+ std::vector<uint8_t> sceneModesOverride = {
+ ANDROID_CONTROL_AE_MODE_ON,
+ ANDROID_CONTROL_AWB_MODE_AUTO,
+ ANDROID_CONTROL_AF_MODE_OFF,
+ };
+ staticMetadata_->addEntry(ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
+ sceneModesOverride);
+
+ uint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
+ staticMetadata_->addEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,
+ aeLockAvailable);
+
+ uint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
+ staticMetadata_->addEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
+ awbLockAvailable);
+
+ char availableControlModes = ANDROID_CONTROL_MODE_AUTO;
+ staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES,
+ availableControlModes);
+
+ /* JPEG static metadata. */
+
+ /*
+ * Create the list of supported thumbnail sizes by inspecting the
+ * available JPEG resolutions collected in streamConfigurations_ and
+ * generate one entry for each aspect ratio.
+ *
+ * The JPEG thumbnailer can freely scale, so pick an arbitrary
+ * (160, 160) size as the bounding rectangle, which is then cropped to
+ * the different supported aspect ratios.
+ */
+ constexpr Size maxJpegThumbnail(160, 160);
+ std::vector<Size> thumbnailSizes;
+ thumbnailSizes.push_back({ 0, 0 });
+ for (const auto &entry : streamConfigurations_) {
+ if (entry.androidFormat != HAL_PIXEL_FORMAT_BLOB)
+ continue;
+
+ Size thumbnailSize = maxJpegThumbnail
+ .boundedToAspectRatio({ entry.resolution.width,
+ entry.resolution.height });
+ thumbnailSizes.push_back(thumbnailSize);
+ }
+
+ std::sort(thumbnailSizes.begin(), thumbnailSizes.end());
+ auto last = std::unique(thumbnailSizes.begin(), thumbnailSizes.end());
+ thumbnailSizes.erase(last, thumbnailSizes.end());
+
+ /* Transform sizes in to a list of integers that can be consumed. */
+ std::vector<int32_t> thumbnailEntries;
+ thumbnailEntries.reserve(thumbnailSizes.size() * 2);
+ for (const auto &size : thumbnailSizes) {
+ thumbnailEntries.push_back(size.width);
+ thumbnailEntries.push_back(size.height);
+ }
+ staticMetadata_->addEntry(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
+ thumbnailEntries);
+
+ staticMetadata_->addEntry(ANDROID_JPEG_MAX_SIZE, maxJpegBufferSize_);
+
+ /* Sensor static metadata. */
+ std::array<int32_t, 2> pixelArraySize;
+ {
+ const Size &size = properties.get(properties::PixelArraySize);
+ pixelArraySize[0] = size.width;
+ pixelArraySize[1] = size.height;
+ staticMetadata_->addEntry(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
+ pixelArraySize);
+ }
+
+ if (properties.contains(properties::UnitCellSize)) {
+ const Size &cellSize = properties.get<Size>(properties::UnitCellSize);
+ std::array<float, 2> physicalSize{
+ cellSize.width * pixelArraySize[0] / 1e6f,
+ cellSize.height * pixelArraySize[1] / 1e6f
+ };
+ staticMetadata_->addEntry(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
+ physicalSize);
+ }
+
+ {
+ const Span<const Rectangle> &rects =
+ properties.get(properties::PixelArrayActiveAreas);
+ std::vector<int32_t> data{
+ static_cast<int32_t>(rects[0].x),
+ static_cast<int32_t>(rects[0].y),
+ static_cast<int32_t>(rects[0].width),
+ static_cast<int32_t>(rects[0].height),
+ };
+ staticMetadata_->addEntry(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
+ data);
+ }
+
+ int32_t sensitivityRange[] = {
+ 32, 2400,
+ };
+ staticMetadata_->addEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
+ sensitivityRange);
+
+ /* Report the color filter arrangement if the camera reports it. */
+ if (properties.contains(properties::draft::ColorFilterArrangement)) {
+ uint8_t filterArr = properties.get(properties::draft::ColorFilterArrangement);
+ staticMetadata_->addEntry(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
+ filterArr);
+ }
+
+ const auto &exposureInfo = controlsInfo.find(&controls::ExposureTime);
+ if (exposureInfo != controlsInfo.end()) {
+ int64_t exposureTimeRange[2] = {
+ exposureInfo->second.min().get<int32_t>() * 1000LL,
+ exposureInfo->second.max().get<int32_t>() * 1000LL,
+ };
+ staticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
+ exposureTimeRange, 2);
+ }
+
+ staticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION, orientation_);
+
+ std::vector<int32_t> testPatternModes = {
+ ANDROID_SENSOR_TEST_PATTERN_MODE_OFF
+ };
+ const auto &testPatternsInfo =
+ controlsInfo.find(&controls::draft::TestPatternMode);
+ if (testPatternsInfo != controlsInfo.end()) {
+ const auto &values = testPatternsInfo->second.values();
+ ASSERT(!values.empty());
+ for (const auto &value : values) {
+ switch (value.get<int32_t>()) {
+ case controls::draft::TestPatternModeOff:
+ /*
+ * ANDROID_SENSOR_TEST_PATTERN_MODE_OFF is
+ * already in testPatternModes.
+ */
+ break;
+
+ case controls::draft::TestPatternModeSolidColor:
+ testPatternModes.push_back(
+ ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR);
+ break;
+
+ case controls::draft::TestPatternModeColorBars:
+ testPatternModes.push_back(
+ ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS);
+ break;
+
+ case controls::draft::TestPatternModeColorBarsFadeToGray:
+ testPatternModes.push_back(
+ ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY);
+ break;
+
+ case controls::draft::TestPatternModePn9:
+ testPatternModes.push_back(
+ ANDROID_SENSOR_TEST_PATTERN_MODE_PN9);
+ break;
+
+ case controls::draft::TestPatternModeCustom1:
+ /* We don't support this yet. */
+ break;
+
+ default:
+ LOG(HAL, Error) << "Unknown test pattern mode: "
+ << value.get<int32_t>();
+ continue;
+ }
+ }
+ }
+ staticMetadata_->addEntry(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
+ testPatternModes);
+
+ uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
+ staticMetadata_->addEntry(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
+ timestampSource);
+
+ if (maxFrameDurationNsec > 0)
+ staticMetadata_->addEntry(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
+ maxFrameDurationNsec);
+
+ /* Statistics static metadata. */
+ uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
+ staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
+ faceDetectMode);
+
+ int32_t maxFaceCount = 0;
+ staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
+ maxFaceCount);
+
+ {
+ std::vector<uint8_t> data;
+ data.reserve(2);
+ const auto &infoMap = controlsInfo.find(&controls::draft::LensShadingMapMode);
+ if (infoMap != controlsInfo.end()) {
+ for (const auto &value : infoMap->second.values())
+ data.push_back(value.get<int32_t>());
+ } else {
+ data.push_back(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF);
+ }
+ staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
+ data);
+ }
+
+ /* Sync static metadata. */
+ int32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
+ staticMetadata_->addEntry(ANDROID_SYNC_MAX_LATENCY, maxLatency);
+
+ /* Flash static metadata. */
+ char flashAvailable = ANDROID_FLASH_INFO_AVAILABLE_FALSE;
+ staticMetadata_->addEntry(ANDROID_FLASH_INFO_AVAILABLE,
+ flashAvailable);
+
+ /* Lens static metadata. */
+ std::vector<float> lensApertures = {
+ 2.53 / 100,
+ };
+ staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_APERTURES,
+ lensApertures);
+
+ uint8_t lensFacing;
+ switch (facing_) {
+ default:
+ case CAMERA_FACING_FRONT:
+ lensFacing = ANDROID_LENS_FACING_FRONT;
+ break;
+ case CAMERA_FACING_BACK:
+ lensFacing = ANDROID_LENS_FACING_BACK;
+ break;
+ case CAMERA_FACING_EXTERNAL:
+ lensFacing = ANDROID_LENS_FACING_EXTERNAL;
+ break;
+ }
+ staticMetadata_->addEntry(ANDROID_LENS_FACING, lensFacing);
+
+ std::vector<float> lensFocalLengths = {
+ 1,
+ };
+ staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
+ lensFocalLengths);
+
+ std::vector<uint8_t> opticalStabilizations = {
+ ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF,
+ };
+ staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
+ opticalStabilizations);
+
+ float hypeFocalDistance = 0;
+ staticMetadata_->addEntry(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
+ hypeFocalDistance);
+
+ float minFocusDistance = 0;
+ staticMetadata_->addEntry(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
+ minFocusDistance);
+
+ /* Noise reduction modes. */
+ {
+ std::vector<uint8_t> data;
+ data.reserve(5);
+ const auto &infoMap = controlsInfo.find(&controls::draft::NoiseReductionMode);
+ if (infoMap != controlsInfo.end()) {
+ for (const auto &value : infoMap->second.values())
+ data.push_back(value.get<int32_t>());
+ } else {
+ data.push_back(ANDROID_NOISE_REDUCTION_MODE_OFF);
+ }
+ staticMetadata_->addEntry(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
+ data);
+ }
+
+ /* Scaler static metadata. */
+
+ /*
+ * \todo The digital zoom factor is a property that depends on the
+ * desired output configuration and the sensor frame size input to the
+ * ISP. This information is not available to the Android HAL, not at
+ * initialization time at least.
+ *
+ * As a workaround rely on pipeline handlers initializing the
+ * ScalerCrop control with the camera default configuration and use the
+ * maximum and minimum crop rectangles to calculate the digital zoom
+ * factor.
+ */
+ float maxZoom = 1.0f;
+ const auto scalerCrop = controlsInfo.find(&controls::ScalerCrop);
+ if (scalerCrop != controlsInfo.end()) {
+ Rectangle min = scalerCrop->second.min().get<Rectangle>();
+ Rectangle max = scalerCrop->second.max().get<Rectangle>();
+ maxZoom = std::min(1.0f * max.width / min.width,
+ 1.0f * max.height / min.height);
+ }
+ staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+ maxZoom);
+
+ std::vector<uint32_t> availableStreamConfigurations;
+ availableStreamConfigurations.reserve(streamConfigurations_.size() * 4);
+ for (const auto &entry : streamConfigurations_) {
+ availableStreamConfigurations.push_back(entry.androidFormat);
+ availableStreamConfigurations.push_back(entry.resolution.width);
+ availableStreamConfigurations.push_back(entry.resolution.height);
+ availableStreamConfigurations.push_back(
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);
+ }
+ staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+ availableStreamConfigurations);
+
+ std::vector<int64_t> availableStallDurations = {
+ ANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,
+ };
+ staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
+ availableStallDurations);
+
+ /* Use the minimum frame duration for all the YUV/RGB formats. */
+ if (minFrameDurationNsec > 0) {
+ std::vector<int64_t> minFrameDurations;
+ minFrameDurations.reserve(streamConfigurations_.size() * 4);
+ for (const auto &entry : streamConfigurations_) {
+ minFrameDurations.push_back(entry.androidFormat);
+ minFrameDurations.push_back(entry.resolution.width);
+ minFrameDurations.push_back(entry.resolution.height);
+ minFrameDurations.push_back(minFrameDurationNsec);
+ }
+ staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
+ minFrameDurations);
+ }
+
+ uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
+ staticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE, croppingType);
+
+ /* Info static metadata. */
+ uint8_t supportedHWLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
+ staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
+ supportedHWLevel);
+
+ /* Request static metadata. */
+ int32_t partialResultCount = 1;
+ staticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
+ partialResultCount);
+
+ {
+ /* Default the value to 2 if not reported by the camera. */
+ uint8_t maxPipelineDepth = 2;
+ const auto &infoMap = controlsInfo.find(&controls::draft::PipelineDepth);
+ if (infoMap != controlsInfo.end())
+ maxPipelineDepth = infoMap->second.max().get<int32_t>();
+ staticMetadata_->addEntry(ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
+ maxPipelineDepth);
+ }
+
+ /* LIMITED does not support reprocessing. */
+ uint32_t maxNumInputStreams = 0;
+ staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
+ maxNumInputStreams);
+
+ std::vector<uint8_t> availableCapabilities = {
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
+ };
+
+ /* Report if camera supports RAW. */
+ bool rawStreamAvailable = false;
+ std::unique_ptr<CameraConfiguration> cameraConfig =
+ camera_->generateConfiguration({ StreamRole::Raw });
+ if (cameraConfig && !cameraConfig->empty()) {
+ const PixelFormatInfo &info =
+ PixelFormatInfo::info(cameraConfig->at(0).pixelFormat);
+ /* Only advertise RAW support if RAW16 is possible. */
+ if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW &&
+ info.bitsPerPixel == 16) {
+ rawStreamAvailable = true;
+ availableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
+ }
+ }
+
+ /* Number of { RAW, YUV, JPEG } supported output streams */
+ int32_t numOutStreams[] = { rawStreamAvailable, 2, 1 };
+ staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
+ numOutStreams);
+
+ staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
+ availableCapabilities);
+
+ std::vector<int32_t> availableCharacteristicsKeys = {
+ ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
+ ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
+ ANDROID_CONTROL_AE_AVAILABLE_MODES,
+ ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+ ANDROID_CONTROL_AE_COMPENSATION_RANGE,
+ ANDROID_CONTROL_AE_COMPENSATION_STEP,
+ ANDROID_CONTROL_AE_LOCK_AVAILABLE,
+ ANDROID_CONTROL_AF_AVAILABLE_MODES,
+ ANDROID_CONTROL_AVAILABLE_EFFECTS,
+ ANDROID_CONTROL_AVAILABLE_MODES,
+ ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
+ ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
+ ANDROID_CONTROL_AWB_AVAILABLE_MODES,
+ ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
+ ANDROID_CONTROL_MAX_REGIONS,
+ ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
+ ANDROID_FLASH_INFO_AVAILABLE,
+ ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
+ ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
+ ANDROID_JPEG_MAX_SIZE,
+ ANDROID_LENS_FACING,
+ ANDROID_LENS_INFO_AVAILABLE_APERTURES,
+ ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
+ ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
+ ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
+ ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
+ ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
+ ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
+ ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
+ ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
+ ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
+ ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+ ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
+ ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+ ANDROID_SCALER_CROPPING_TYPE,
+ ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
+ ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
+ ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
+ ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
+ ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
+ ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
+ ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
+ ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
+ ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
+ ANDROID_SENSOR_ORIENTATION,
+ ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
+ ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
+ ANDROID_SYNC_MAX_LATENCY,
+ };
+ staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
+ availableCharacteristicsKeys);
+
+ std::vector<int32_t> availableRequestKeys = {
+ ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+ ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+ ANDROID_CONTROL_AE_LOCK,
+ ANDROID_CONTROL_AE_MODE,
+ ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+ ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+ ANDROID_CONTROL_AF_MODE,
+ ANDROID_CONTROL_AF_TRIGGER,
+ ANDROID_CONTROL_AWB_LOCK,
+ ANDROID_CONTROL_AWB_MODE,
+ ANDROID_CONTROL_CAPTURE_INTENT,
+ ANDROID_CONTROL_EFFECT_MODE,
+ ANDROID_CONTROL_MODE,
+ ANDROID_CONTROL_SCENE_MODE,
+ ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+ ANDROID_FLASH_MODE,
+ ANDROID_JPEG_ORIENTATION,
+ ANDROID_JPEG_QUALITY,
+ ANDROID_JPEG_THUMBNAIL_QUALITY,
+ ANDROID_JPEG_THUMBNAIL_SIZE,
+ ANDROID_LENS_APERTURE,
+ ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+ ANDROID_NOISE_REDUCTION_MODE,
+ ANDROID_SCALER_CROP_REGION,
+ ANDROID_STATISTICS_FACE_DETECT_MODE
+ };
+ staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,
+ availableRequestKeys);
+
+ std::vector<int32_t> availableResultKeys = {
+ ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+ ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+ ANDROID_CONTROL_AE_LOCK,
+ ANDROID_CONTROL_AE_MODE,
+ ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+ ANDROID_CONTROL_AE_STATE,
+ ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+ ANDROID_CONTROL_AF_MODE,
+ ANDROID_CONTROL_AF_STATE,
+ ANDROID_CONTROL_AF_TRIGGER,
+ ANDROID_CONTROL_AWB_LOCK,
+ ANDROID_CONTROL_AWB_MODE,
+ ANDROID_CONTROL_AWB_STATE,
+ ANDROID_CONTROL_CAPTURE_INTENT,
+ ANDROID_CONTROL_EFFECT_MODE,
+ ANDROID_CONTROL_MODE,
+ ANDROID_CONTROL_SCENE_MODE,
+ ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+ ANDROID_FLASH_MODE,
+ ANDROID_FLASH_STATE,
+ ANDROID_JPEG_GPS_COORDINATES,
+ ANDROID_JPEG_GPS_PROCESSING_METHOD,
+ ANDROID_JPEG_GPS_TIMESTAMP,
+ ANDROID_JPEG_ORIENTATION,
+ ANDROID_JPEG_QUALITY,
+ ANDROID_JPEG_SIZE,
+ ANDROID_JPEG_THUMBNAIL_QUALITY,
+ ANDROID_JPEG_THUMBNAIL_SIZE,
+ ANDROID_LENS_APERTURE,
+ ANDROID_LENS_FOCAL_LENGTH,
+ ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+ ANDROID_LENS_STATE,
+ ANDROID_NOISE_REDUCTION_MODE,
+ ANDROID_REQUEST_PIPELINE_DEPTH,
+ ANDROID_SCALER_CROP_REGION,
+ ANDROID_SENSOR_EXPOSURE_TIME,
+ ANDROID_SENSOR_FRAME_DURATION,
+ ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,
+ ANDROID_SENSOR_TEST_PATTERN_MODE,
+ ANDROID_SENSOR_TIMESTAMP,
+ ANDROID_STATISTICS_FACE_DETECT_MODE,
+ ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
+ ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
+ ANDROID_STATISTICS_SCENE_FLICKER,
+ };
+ staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,
+ availableResultKeys);
+
+ if (!staticMetadata_->isValid()) {
+ LOG(HAL, Error) << "Failed to construct static metadata";
+ staticMetadata_.reset();
+ return -EINVAL;
+ }
+
+ if (staticMetadata_->resized()) {
+ auto [entryCount, dataCount] = staticMetadata_->usage();
+ LOG(HAL, Info)
+ << "Static metadata resized: " << entryCount
+ << " entries and " << dataCount << " bytes used";
+ }
+
+ return 0;
+}
+
+/* Translate Android format code to libcamera pixel format. */
+PixelFormat CameraCapabilities::toPixelFormat(int format) const
+{
+ auto it = formatsMap_.find(format);
+ if (it == formatsMap_.end()) {
+ LOG(HAL, Error) << "Requested format " << utils::hex(format)
+ << " not supported";
+ return PixelFormat();
+ }
+
+ return it->second;
+}
+
+std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplatePreview() const
+{
+ /*
+ * \todo Keep this in sync with the actual number of entries.
+ * Currently: 20 entries, 35 bytes
+ */
+ auto requestTemplate = std::make_unique<CameraMetadata>(21, 36);
+ if (!requestTemplate->isValid()) {
+ return nullptr;
+ }
+
+ /* Get the FPS range registered in the static metadata. */
+ camera_metadata_ro_entry_t entry;
+ bool found = staticMetadata_->getEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+ &entry);
+ if (!found) {
+ LOG(HAL, Error) << "Cannot create capture template without FPS range";
+ return nullptr;
+ }
+
+ /*
+ * Assume the AE_AVAILABLE_TARGET_FPS_RANGE static metadata
+ * has been assembled as {{min, max} {max, max}}.
+ */
+ requestTemplate->addEntry(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+ entry.data.i32, 2);
+
+ uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
+ requestTemplate->addEntry(ANDROID_CONTROL_AE_MODE, aeMode);
+
+ int32_t aeExposureCompensation = 0;
+ requestTemplate->addEntry(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+ aeExposureCompensation);
+
+ uint8_t aePrecaptureTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;
+ requestTemplate->addEntry(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+ aePrecaptureTrigger);
+
+ uint8_t aeLock = ANDROID_CONTROL_AE_LOCK_OFF;
+ requestTemplate->addEntry(ANDROID_CONTROL_AE_LOCK, aeLock);
+
+ uint8_t aeAntibandingMode = ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
+ requestTemplate->addEntry(ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+ aeAntibandingMode);
+
+ uint8_t afMode = ANDROID_CONTROL_AF_MODE_OFF;
+ requestTemplate->addEntry(ANDROID_CONTROL_AF_MODE, afMode);
+
+ uint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;
+ requestTemplate->addEntry(ANDROID_CONTROL_AF_TRIGGER, afTrigger);
+
+ uint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO;
+ requestTemplate->addEntry(ANDROID_CONTROL_AWB_MODE, awbMode);
+
+ uint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;
+ requestTemplate->addEntry(ANDROID_CONTROL_AWB_LOCK, awbLock);
+
+ uint8_t flashMode = ANDROID_FLASH_MODE_OFF;
+ requestTemplate->addEntry(ANDROID_FLASH_MODE, flashMode);
+
+ uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
+ requestTemplate->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE,
+ faceDetectMode);
+
+ uint8_t noiseReduction = ANDROID_NOISE_REDUCTION_MODE_OFF;
+ requestTemplate->addEntry(ANDROID_NOISE_REDUCTION_MODE,
+ noiseReduction);
+
+ uint8_t aberrationMode = ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF;
+ requestTemplate->addEntry(ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
+ aberrationMode);
+
+ uint8_t controlMode = ANDROID_CONTROL_MODE_AUTO;
+ requestTemplate->addEntry(ANDROID_CONTROL_MODE, controlMode);
+
+ float lensAperture = 2.53 / 100;
+ requestTemplate->addEntry(ANDROID_LENS_APERTURE, lensAperture);
+
+ uint8_t opticalStabilization = ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
+ requestTemplate->addEntry(ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+ opticalStabilization);
+
+ uint8_t captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
+ requestTemplate->addEntry(ANDROID_CONTROL_CAPTURE_INTENT,
+ captureIntent);
+
+ return requestTemplate;
+}
+
+std::unique_ptr<CameraMetadata> CameraCapabilities::requestTemplateVideo() const
+{
+ std::unique_ptr<CameraMetadata> previewTemplate = requestTemplatePreview();
+ if (!previewTemplate)
+ return nullptr;
+
+ /*
+ * The video template requires a fixed FPS range. Everything else
+ * stays the same as the preview template.
+ */
+ camera_metadata_ro_entry_t entry;
+ staticMetadata_->getEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+ &entry);
+
+ /*
+ * Assume the AE_AVAILABLE_TARGET_FPS_RANGE static metadata
+ * has been assembled as {{min, max} {max, max}}.
+ */
+ previewTemplate->updateEntry(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+ entry.data.i32 + 2, 2);
+
+ return previewTemplate;
+}
diff --git a/src/android/camera_capabilities.h b/src/android/camera_capabilities.h
new file mode 100644
index 00000000..f511607b
--- /dev/null
+++ b/src/android/camera_capabilities.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2021, Google Inc.
+ *
+ * camera_capabilities.h - Camera static properties manager
+ */
+#ifndef __ANDROID_CAMERA_CAPABILITIES_H__
+#define __ANDROID_CAMERA_CAPABILITIES_H__
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <libcamera/camera.h>
+#include <libcamera/class.h>
+#include <libcamera/formats.h>
+#include <libcamera/geometry.h>
+
+#include "camera_metadata.h"
+
+class CameraCapabilities
+{
+public:
+ CameraCapabilities() = default;
+
+ int initialize(std::shared_ptr<libcamera::Camera> camera,
+ int orientation, int facing);
+
+ CameraMetadata *staticMetadata() const { return staticMetadata_.get(); }
+ libcamera::PixelFormat toPixelFormat(int format) const;
+ unsigned int maxJpegBufferSize() const { return maxJpegBufferSize_; }
+
+ std::unique_ptr<CameraMetadata> requestTemplatePreview() const;
+ std::unique_ptr<CameraMetadata> requestTemplateVideo() const;
+
+private:
+ LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraCapabilities)
+
+ struct Camera3StreamConfiguration {
+ libcamera::Size resolution;
+ int androidFormat;
+ };
+
+ std::vector<libcamera::Size>
+ getYUVResolutions(libcamera::CameraConfiguration *cameraConfig,
+ const libcamera::PixelFormat &pixelFormat,
+ const std::vector<libcamera::Size> &resolutions);
+ std::vector<libcamera::Size>
+ getRawResolutions(const libcamera::PixelFormat &pixelFormat);
+ int initializeStreamConfigurations();
+
+ int initializeStaticMetadata();
+
+ std::shared_ptr<libcamera::Camera> camera_;
+
+ int facing_;
+ int orientation_;
+
+ std::vector<Camera3StreamConfiguration> streamConfigurations_;
+ std::map<int, libcamera::PixelFormat> formatsMap_;
+ std::unique_ptr<CameraMetadata> staticMetadata_;
+ unsigned int maxJpegBufferSize_;
+};
+
+#endif /* __ANDROID_CAMERA_CAPABILITIES_H__ */
diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
index 8c71fd06..4bd125d7 100644
--- a/src/android/camera_device.cpp
+++ b/src/android/camera_device.cpp
@@ -10,11 +10,8 @@
#include "camera_ops.h"
#include "post_processor.h"
-#include <array>
-#include <cmath>
#include <fstream>
#include <sys/mman.h>
-#include <tuple>
#include <unistd.h>
#include <vector>
@@ -23,7 +20,6 @@
#include <libcamera/formats.h>
#include <libcamera/property_ids.h>
-#include "libcamera/internal/formats.h"
#include "libcamera/internal/log.h"
#include "libcamera/internal/thread.h"
#include "libcamera/internal/utils.h"
@@ -37,94 +33,6 @@ LOG_DECLARE_CATEGORY(HAL)
namespace {
/*
- * \var camera3Resolutions
- * \brief The list of image resolutions defined as mandatory to be supported by
- * the Android Camera3 specification
- */
-const std::vector<Size> camera3Resolutions = {
- { 320, 240 },
- { 640, 480 },
- { 1280, 720 },
- { 1920, 1080 }
-};
-
-/*
- * \struct Camera3Format
- * \brief Data associated with an Android format identifier
- * \var libcameraFormats List of libcamera pixel formats compatible with the
- * Android format
- * \var name The human-readable representation of the Android format code
- */
-struct Camera3Format {
- std::vector<PixelFormat> libcameraFormats;
- bool mandatory;
- const char *name;
-};
-
-/*
- * \var camera3FormatsMap
- * \brief Associate Android format code with ancillary data
- */
-const std::map<int, const Camera3Format> camera3FormatsMap = {
- {
- HAL_PIXEL_FORMAT_BLOB, {
- { formats::MJPEG },
- true,
- "BLOB"
- }
- }, {
- HAL_PIXEL_FORMAT_YCbCr_420_888, {
- { formats::NV12, formats::NV21 },
- true,
- "YCbCr_420_888"
- }
- }, {
- /*
- * \todo Translate IMPLEMENTATION_DEFINED inspecting the gralloc
- * usage flag. For now, copy the YCbCr_420 configuration.
- */
- HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, {
- { formats::NV12, formats::NV21 },
- true,
- "IMPLEMENTATION_DEFINED"
- }
- }, {
- HAL_PIXEL_FORMAT_RAW10, {
- {
- formats::SBGGR10_CSI2P,
- formats::SGBRG10_CSI2P,
- formats::SGRBG10_CSI2P,
- formats::SRGGB10_CSI2P
- },
- false,
- "RAW10"
- }
- }, {
- HAL_PIXEL_FORMAT_RAW12, {
- {
- formats::SBGGR12_CSI2P,
- formats::SGBRG12_CSI2P,
- formats::SGRBG12_CSI2P,
- formats::SRGGB12_CSI2P
- },
- false,
- "RAW12"
- }
- }, {
- HAL_PIXEL_FORMAT_RAW16, {
- {
- formats::SBGGR16,
- formats::SGBRG16,
- formats::SGRBG16,
- formats::SRGGB16
- },
- false,
- "RAW16"
- }
- },
-};
-
-/*
* \struct Camera3StreamConfig
* \brief Data to store StreamConfiguration associated with camera3_stream(s)
* \var streams List of the pairs of a stream requested by Android HAL client
@@ -512,242 +420,7 @@ int CameraDevice::initialize(const CameraConfigData *cameraConfigData)
orientation_ = 0;
}
- /* Acquire the camera and initialize available stream configurations. */
- int ret = camera_->acquire();
- if (ret) {
- LOG(HAL, Error) << "Failed to temporarily acquire the camera";
- return ret;
- }
-
- ret = initializeStreamConfigurations();
- camera_->release();
- return ret;
-}
-
-std::vector<Size> CameraDevice::getYUVResolutions(CameraConfiguration *cameraConfig,
- const PixelFormat &pixelFormat,
- const std::vector<Size> &resolutions)
-{
- std::vector<Size> supportedResolutions;
-
- StreamConfiguration &cfg = cameraConfig->at(0);
- for (const Size &res : resolutions) {
- cfg.pixelFormat = pixelFormat;
- cfg.size = res;
-
- CameraConfiguration::Status status = cameraConfig->validate();
- if (status != CameraConfiguration::Valid) {
- LOG(HAL, Debug) << cfg.toString() << " not supported";
- continue;
- }
-
- LOG(HAL, Debug) << cfg.toString() << " supported";
-
- supportedResolutions.push_back(res);
- }
-
- return supportedResolutions;
-}
-
-std::vector<Size> CameraDevice::getRawResolutions(const libcamera::PixelFormat &pixelFormat)
-{
- std::unique_ptr<CameraConfiguration> cameraConfig =
- camera_->generateConfiguration({ StreamRole::Raw });
- StreamConfiguration &cfg = cameraConfig->at(0);
- const StreamFormats &formats = cfg.formats();
- std::vector<Size> supportedResolutions = formats.sizes(pixelFormat);
-
- return supportedResolutions;
-}
-
-/*
- * Initialize the format conversion map to translate from Android format
- * identifier to libcamera pixel formats and fill in the list of supported
- * stream configurations to be reported to the Android camera framework through
- * the static stream configuration metadata.
- */
-int CameraDevice::initializeStreamConfigurations()
-{
- /*
- * Get the maximum output resolutions
- * \todo Get this from the camera properties once defined
- */
- std::unique_ptr<CameraConfiguration> cameraConfig =
- camera_->generateConfiguration({ StillCapture });
- if (!cameraConfig) {
- LOG(HAL, Error) << "Failed to get maximum resolution";
- return -EINVAL;
- }
- StreamConfiguration &cfg = cameraConfig->at(0);
-
- /*
- * \todo JPEG - Adjust the maximum available resolution by taking the
- * JPEG encoder requirements into account (alignment and aspect ratio).
- */
- const Size maxRes = cfg.size;
- LOG(HAL, Debug) << "Maximum supported resolution: " << maxRes.toString();
-
- /*
- * Build the list of supported image resolutions.
- *
- * The resolutions listed in camera3Resolution are mandatory to be
- * supported, up to the camera maximum resolution.
- *
- * Augment the list by adding resolutions calculated from the camera
- * maximum one.
- */
- std::vector<Size> cameraResolutions;
- std::copy_if(camera3Resolutions.begin(), camera3Resolutions.end(),
- std::back_inserter(cameraResolutions),
- [&](const Size &res) { return res < maxRes; });
-
- /*
- * The Camera3 specification suggests adding 1/2 and 1/4 of the maximum
- * resolution.
- */
- for (unsigned int divider = 2;; divider <<= 1) {
- Size derivedSize{
- maxRes.width / divider,
- maxRes.height / divider,
- };
-
- if (derivedSize.width < 320 ||
- derivedSize.height < 240)
- break;
-
- cameraResolutions.push_back(derivedSize);
- }
- cameraResolutions.push_back(maxRes);
-
- /* Remove duplicated entries from the list of supported resolutions. */
- std::sort(cameraResolutions.begin(), cameraResolutions.end());
- auto last = std::unique(cameraResolutions.begin(), cameraResolutions.end());
- cameraResolutions.erase(last, cameraResolutions.end());
-
- /*
- * Build the list of supported camera formats.
- *
- * To each Android format a list of compatible libcamera formats is
- * associated. The first libcamera format that tests successful is added
- * to the format translation map used when configuring the streams.
- * It is then tested against the list of supported camera resolutions to
- * build the stream configuration map reported through the camera static
- * metadata.
- */
- Size maxJpegSize;
- for (const auto &format : camera3FormatsMap) {
- int androidFormat = format.first;
- const Camera3Format &camera3Format = format.second;
- const std::vector<PixelFormat> &libcameraFormats =
- camera3Format.libcameraFormats;
-
- LOG(HAL, Debug) << "Trying to map Android format "
- << camera3Format.name;
-
- /*
- * JPEG is always supported, either produced directly by the
- * camera, or encoded in the HAL.
- */
- if (androidFormat == HAL_PIXEL_FORMAT_BLOB) {
- formatsMap_[androidFormat] = formats::MJPEG;
- LOG(HAL, Debug) << "Mapped Android format "
- << camera3Format.name << " to "
- << formats::MJPEG.toString()
- << " (fixed mapping)";
- continue;
- }
-
- /*
- * Test the libcamera formats that can produce images
- * compatible with the format defined by Android.
- */
- PixelFormat mappedFormat;
- for (const PixelFormat &pixelFormat : libcameraFormats) {
-
- LOG(HAL, Debug) << "Testing " << pixelFormat.toString();
-
- /*
- * The stream configuration size can be adjusted,
- * not the pixel format.
- *
- * \todo This could be simplified once all pipeline
- * handlers will report the StreamFormats list of
- * supported formats.
- */
- cfg.pixelFormat = pixelFormat;
-
- CameraConfiguration::Status status = cameraConfig->validate();
- if (status != CameraConfiguration::Invalid &&
- cfg.pixelFormat == pixelFormat) {
- mappedFormat = pixelFormat;
- break;
- }
- }
-
- if (!mappedFormat.isValid()) {
- /* If the format is not mandatory, skip it. */
- if (!camera3Format.mandatory)
- continue;
-
- LOG(HAL, Error)
- << "Failed to map mandatory Android format "
- << camera3Format.name << " ("
- << utils::hex(androidFormat) << "): aborting";
- return -EINVAL;
- }
-
- /*
- * Record the mapping and then proceed to generate the
- * stream configurations map, by testing the image resolutions.
- */
- formatsMap_[androidFormat] = mappedFormat;
- LOG(HAL, Debug) << "Mapped Android format "
- << camera3Format.name << " to "
- << mappedFormat.toString();
-
- std::vector<Size> resolutions;
- const PixelFormatInfo &info = PixelFormatInfo::info(mappedFormat);
- if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW)
- resolutions = getRawResolutions(mappedFormat);
- else
- resolutions = getYUVResolutions(cameraConfig.get(),
- mappedFormat,
- cameraResolutions);
-
- for (const Size &res : resolutions) {
- streamConfigurations_.push_back({ res, androidFormat });
-
- /*
- * If the format is HAL_PIXEL_FORMAT_YCbCr_420_888
- * from which JPEG is produced, add an entry for
- * the JPEG stream.
- *
- * \todo Wire the JPEG encoder to query the supported
- * sizes provided a list of formats it can encode.
- *
- * \todo Support JPEG streams produced by the Camera
- * natively.
- */
- if (androidFormat == HAL_PIXEL_FORMAT_YCbCr_420_888) {
- streamConfigurations_.push_back(
- { res, HAL_PIXEL_FORMAT_BLOB });
- maxJpegSize = std::max(maxJpegSize, res);
- }
- }
-
- /*
- * \todo Calculate the maximum JPEG buffer size by asking the
- * encoder giving the maximum frame size required.
- */
- maxJpegBufferSize_ = maxJpegSize.width * maxJpegSize.height * 1.5;
- }
-
- LOG(HAL, Debug) << "Collected stream configuration map: ";
- for (const auto &entry : streamConfigurations_)
- LOG(HAL, Debug) << "{ " << entry.resolution.toString() << " - "
- << utils::hex(entry.androidFormat) << " }";
-
- return 0;
+ return capabilities_.initialize(camera_, orientation_, facing_);
}
/*
@@ -817,802 +490,19 @@ void CameraDevice::stop()
state_ = State::Stopped;
}
-void CameraDevice::setCallbacks(const camera3_callback_ops_t *callbacks)
+unsigned int CameraDevice::maxJpegBufferSize() const
{
- callbacks_ = callbacks;
+ return capabilities_.maxJpegBufferSize();
}
-/*
- * Return static information for the camera.
- */
-const camera_metadata_t *CameraDevice::getStaticMetadata()
-{
- if (staticMetadata_)
- return staticMetadata_->get();
-
- staticMetadata_ = std::make_unique<CameraMetadata>(64, 1024);
- if (!staticMetadata_->isValid()) {
- LOG(HAL, Error) << "Failed to allocate static metadata";
- staticMetadata_.reset();
- return nullptr;
- }
-
- const ControlInfoMap &controlsInfo = camera_->controls();
- const ControlList &properties = camera_->properties();
-
- /* Color correction static metadata. */
- {
- std::vector<uint8_t> data;
- data.reserve(3);
- const auto &infoMap = controlsInfo.find(&controls::draft::ColorCorrectionAberrationMode);
- if (infoMap != controlsInfo.end()) {
- for (const auto &value : infoMap->second.values())
- data.push_back(value.get<int32_t>());
- } else {
- data.push_back(ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF);
- }
- staticMetadata_->addEntry(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
- data);
- }
-
- /* Control static metadata. */
- std::vector<uint8_t> aeAvailableAntiBandingModes = {
- ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF,
- ANDROID_CONTROL_AE_ANTIBANDING_MODE_50HZ,
- ANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ,
- ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO,
- };
- staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
- aeAvailableAntiBandingModes);
-
- std::vector<uint8_t> aeAvailableModes = {
- ANDROID_CONTROL_AE_MODE_ON,
- };
- staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,
- aeAvailableModes);
-
- int64_t minFrameDurationNsec = -1;
- int64_t maxFrameDurationNsec = -1;
- const auto frameDurationsInfo = controlsInfo.find(&controls::FrameDurationLimits);
- if (frameDurationsInfo != controlsInfo.end()) {
- minFrameDurationNsec = frameDurationsInfo->second.min().get<int64_t>() * 1000;
- maxFrameDurationNsec = frameDurationsInfo->second.max().get<int64_t>() * 1000;
-
- /*
- * Adjust the minimum frame duration to comply with Android
- * requirements. The camera service mandates all preview/record
- * streams to have a minimum frame duration < 33,366 milliseconds
- * (see MAX_PREVIEW_RECORD_DURATION_NS in the camera service
- * implementation).
- *
- * If we're close enough (+ 500 useconds) to that value, round
- * the minimum frame duration of the camera to an accepted
- * value.
- */
- static constexpr int64_t MAX_PREVIEW_RECORD_DURATION_NS = 1e9 / 29.97;
- if (minFrameDurationNsec > MAX_PREVIEW_RECORD_DURATION_NS &&
- minFrameDurationNsec < MAX_PREVIEW_RECORD_DURATION_NS + 500000)
- minFrameDurationNsec = MAX_PREVIEW_RECORD_DURATION_NS - 1000;
-
- /*
- * The AE routine frame rate limits are computed using the frame
- * duration limits, as libcamera clips the AE routine to the
- * frame durations.
- */
- int32_t maxFps = std::round(1e9 / minFrameDurationNsec);
- int32_t minFps = std::round(1e9 / maxFrameDurationNsec);
- minFps = std::max(1, minFps);
-
- /*
- * Force rounding errors so that we have the proper frame
- * durations for when we reuse these variables later
- */
- minFrameDurationNsec = 1e9 / maxFps;
- maxFrameDurationNsec = 1e9 / minFps;
-
- /*
- * Register to the camera service {min, max} and {max, max}
- * intervals as requested by the metadata documentation.
- */
- int32_t availableAeFpsTarget[] = {
- minFps, maxFps, maxFps, maxFps
- };
- staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
- availableAeFpsTarget);
- }
-
- std::vector<int32_t> aeCompensationRange = {
- 0, 0,
- };
- staticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_RANGE,
- aeCompensationRange);
-
- const camera_metadata_rational_t aeCompensationStep[] = {
- { 0, 1 }
- };
- staticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_STEP,
- aeCompensationStep);
-
- std::vector<uint8_t> availableAfModes = {
- ANDROID_CONTROL_AF_MODE_OFF,
- };
- staticMetadata_->addEntry(ANDROID_CONTROL_AF_AVAILABLE_MODES,
- availableAfModes);
-
- std::vector<uint8_t> availableEffects = {
- ANDROID_CONTROL_EFFECT_MODE_OFF,
- };
- staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_EFFECTS,
- availableEffects);
-
- std::vector<uint8_t> availableSceneModes = {
- ANDROID_CONTROL_SCENE_MODE_DISABLED,
- };
- staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
- availableSceneModes);
-
- std::vector<uint8_t> availableStabilizationModes = {
- ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF,
- };
- staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
- availableStabilizationModes);
-
- /*
- * \todo Inspect the Camera capabilities to report the available
- * AWB modes. Default to AUTO as CTS tests require it.
- */
- std::vector<uint8_t> availableAwbModes = {
- ANDROID_CONTROL_AWB_MODE_AUTO,
- };
- staticMetadata_->addEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES,
- availableAwbModes);
-
- std::vector<int32_t> availableMaxRegions = {
- 0, 0, 0,
- };
- staticMetadata_->addEntry(ANDROID_CONTROL_MAX_REGIONS,
- availableMaxRegions);
-
- std::vector<uint8_t> sceneModesOverride = {
- ANDROID_CONTROL_AE_MODE_ON,
- ANDROID_CONTROL_AWB_MODE_AUTO,
- ANDROID_CONTROL_AF_MODE_OFF,
- };
- staticMetadata_->addEntry(ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
- sceneModesOverride);
-
- uint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
- staticMetadata_->addEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,
- aeLockAvailable);
-
- uint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
- staticMetadata_->addEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
- awbLockAvailable);
-
- char availableControlModes = ANDROID_CONTROL_MODE_AUTO;
- staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES,
- availableControlModes);
-
- /* JPEG static metadata. */
-
- /*
- * Create the list of supported thumbnail sizes by inspecting the
- * available JPEG resolutions collected in streamConfigurations_ and
- * generate one entry for each aspect ratio.
- *
- * The JPEG thumbnailer can freely scale, so pick an arbitrary
- * (160, 160) size as the bounding rectangle, which is then cropped to
- * the different supported aspect ratios.
- */
- constexpr Size maxJpegThumbnail(160, 160);
- std::vector<Size> thumbnailSizes;
- thumbnailSizes.push_back({ 0, 0 });
- for (const auto &entry : streamConfigurations_) {
- if (entry.androidFormat != HAL_PIXEL_FORMAT_BLOB)
- continue;
-
- Size thumbnailSize = maxJpegThumbnail
- .boundedToAspectRatio({ entry.resolution.width,
- entry.resolution.height });
- thumbnailSizes.push_back(thumbnailSize);
- }
-
- std::sort(thumbnailSizes.begin(), thumbnailSizes.end());
- auto last = std::unique(thumbnailSizes.begin(), thumbnailSizes.end());
- thumbnailSizes.erase(last, thumbnailSizes.end());
-
- /* Transform sizes in to a list of integers that can be consumed. */
- std::vector<int32_t> thumbnailEntries;
- thumbnailEntries.reserve(thumbnailSizes.size() * 2);
- for (const auto &size : thumbnailSizes) {
- thumbnailEntries.push_back(size.width);
- thumbnailEntries.push_back(size.height);
- }
- staticMetadata_->addEntry(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
- thumbnailEntries);
-
- staticMetadata_->addEntry(ANDROID_JPEG_MAX_SIZE, maxJpegBufferSize_);
-
- /* Sensor static metadata. */
- std::array<int32_t, 2> pixelArraySize;
- {
- const Size &size = properties.get(properties::PixelArraySize);
- pixelArraySize[0] = size.width;
- pixelArraySize[1] = size.height;
- staticMetadata_->addEntry(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
- pixelArraySize);
- }
-
- if (properties.contains(properties::UnitCellSize)) {
- const Size &cellSize = properties.get<Size>(properties::UnitCellSize);
- std::array<float, 2> physicalSize{
- cellSize.width * pixelArraySize[0] / 1e6f,
- cellSize.height * pixelArraySize[1] / 1e6f
- };
- staticMetadata_->addEntry(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
- physicalSize);
- }
-
- {
- const Span<const Rectangle> &rects =
- properties.get(properties::PixelArrayActiveAreas);
- std::vector<int32_t> data{
- static_cast<int32_t>(rects[0].x),
- static_cast<int32_t>(rects[0].y),
- static_cast<int32_t>(rects[0].width),
- static_cast<int32_t>(rects[0].height),
- };
- staticMetadata_->addEntry(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
- data);
- }
-
- int32_t sensitivityRange[] = {
- 32, 2400,
- };
- staticMetadata_->addEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
- sensitivityRange);
-
- /* Report the color filter arrangement if the camera reports it. */
- if (properties.contains(properties::draft::ColorFilterArrangement)) {
- uint8_t filterArr = properties.get(properties::draft::ColorFilterArrangement);
- staticMetadata_->addEntry(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
- filterArr);
- }
-
- const auto &exposureInfo = controlsInfo.find(&controls::ExposureTime);
- if (exposureInfo != controlsInfo.end()) {
- int64_t exposureTimeRange[2] = {
- exposureInfo->second.min().get<int32_t>() * 1000LL,
- exposureInfo->second.max().get<int32_t>() * 1000LL,
- };
- staticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
- exposureTimeRange, 2);
- }
-
- staticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION, orientation_);
-
- std::vector<int32_t> testPatternModes = {
- ANDROID_SENSOR_TEST_PATTERN_MODE_OFF
- };
- const auto &testPatternsInfo =
- controlsInfo.find(&controls::draft::TestPatternMode);
- if (testPatternsInfo != controlsInfo.end()) {
- const auto &values = testPatternsInfo->second.values();
- ASSERT(!values.empty());
- for (const auto &value : values) {
- switch (value.get<int32_t>()) {
- case controls::draft::TestPatternModeOff:
- /*
- * ANDROID_SENSOR_TEST_PATTERN_MODE_OFF is
- * already in testPatternModes.
- */
- break;
-
- case controls::draft::TestPatternModeSolidColor:
- testPatternModes.push_back(
- ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR);
- break;
-
- case controls::draft::TestPatternModeColorBars:
- testPatternModes.push_back(
- ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS);
- break;
-
- case controls::draft::TestPatternModeColorBarsFadeToGray:
- testPatternModes.push_back(
- ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY);
- break;
-
- case controls::draft::TestPatternModePn9:
- testPatternModes.push_back(
- ANDROID_SENSOR_TEST_PATTERN_MODE_PN9);
- break;
-
- case controls::draft::TestPatternModeCustom1:
- /* We don't support this yet. */
- break;
-
- default:
- LOG(HAL, Error) << "Unknown test pattern mode: "
- << value.get<int32_t>();
- continue;
- }
- }
- }
- staticMetadata_->addEntry(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
- testPatternModes);
-
- uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
- staticMetadata_->addEntry(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
- timestampSource);
-
- if (maxFrameDurationNsec > 0)
- staticMetadata_->addEntry(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
- maxFrameDurationNsec);
-
- /* Statistics static metadata. */
- uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
- staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
- faceDetectMode);
-
- int32_t maxFaceCount = 0;
- staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
- maxFaceCount);
-
- {
- std::vector<uint8_t> data;
- data.reserve(2);
- const auto &infoMap = controlsInfo.find(&controls::draft::LensShadingMapMode);
- if (infoMap != controlsInfo.end()) {
- for (const auto &value : infoMap->second.values())
- data.push_back(value.get<int32_t>());
- } else {
- data.push_back(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF);
- }
- staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
- data);
- }
-
- /* Sync static metadata. */
- int32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
- staticMetadata_->addEntry(ANDROID_SYNC_MAX_LATENCY, maxLatency);
-
- /* Flash static metadata. */
- char flashAvailable = ANDROID_FLASH_INFO_AVAILABLE_FALSE;
- staticMetadata_->addEntry(ANDROID_FLASH_INFO_AVAILABLE,
- flashAvailable);
-
- /* Lens static metadata. */
- std::vector<float> lensApertures = {
- 2.53 / 100,
- };
- staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_APERTURES,
- lensApertures);
-
- uint8_t lensFacing;
- switch (facing_) {
- default:
- case CAMERA_FACING_FRONT:
- lensFacing = ANDROID_LENS_FACING_FRONT;
- break;
- case CAMERA_FACING_BACK:
- lensFacing = ANDROID_LENS_FACING_BACK;
- break;
- case CAMERA_FACING_EXTERNAL:
- lensFacing = ANDROID_LENS_FACING_EXTERNAL;
- break;
- }
- staticMetadata_->addEntry(ANDROID_LENS_FACING, lensFacing);
-
- std::vector<float> lensFocalLengths = {
- 1,
- };
- staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
- lensFocalLengths);
-
- std::vector<uint8_t> opticalStabilizations = {
- ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF,
- };
- staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
- opticalStabilizations);
-
- float hypeFocalDistance = 0;
- staticMetadata_->addEntry(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
- hypeFocalDistance);
-
- float minFocusDistance = 0;
- staticMetadata_->addEntry(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
- minFocusDistance);
-
- /* Noise reduction modes. */
- {
- std::vector<uint8_t> data;
- data.reserve(5);
- const auto &infoMap = controlsInfo.find(&controls::draft::NoiseReductionMode);
- if (infoMap != controlsInfo.end()) {
- for (const auto &value : infoMap->second.values())
- data.push_back(value.get<int32_t>());
- } else {
- data.push_back(ANDROID_NOISE_REDUCTION_MODE_OFF);
- }
- staticMetadata_->addEntry(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
- data);
- }
-
- /* Scaler static metadata. */
-
- /*
- * \todo The digital zoom factor is a property that depends on the
- * desired output configuration and the sensor frame size input to the
- * ISP. This information is not available to the Android HAL, not at
- * initialization time at least.
- *
- * As a workaround rely on pipeline handlers initializing the
- * ScalerCrop control with the camera default configuration and use the
- * maximum and minimum crop rectangles to calculate the digital zoom
- * factor.
- */
- float maxZoom = 1.0f;
- const auto scalerCrop = controlsInfo.find(&controls::ScalerCrop);
- if (scalerCrop != controlsInfo.end()) {
- Rectangle min = scalerCrop->second.min().get<Rectangle>();
- Rectangle max = scalerCrop->second.max().get<Rectangle>();
- maxZoom = std::min(1.0f * max.width / min.width,
- 1.0f * max.height / min.height);
- }
- staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
- maxZoom);
-
- std::vector<uint32_t> availableStreamConfigurations;
- availableStreamConfigurations.reserve(streamConfigurations_.size() * 4);
- for (const auto &entry : streamConfigurations_) {
- availableStreamConfigurations.push_back(entry.androidFormat);
- availableStreamConfigurations.push_back(entry.resolution.width);
- availableStreamConfigurations.push_back(entry.resolution.height);
- availableStreamConfigurations.push_back(
- ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);
- }
- staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
- availableStreamConfigurations);
-
- std::vector<int64_t> availableStallDurations = {
- ANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,
- };
- staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
- availableStallDurations);
-
- /* Use the minimum frame duration for all the YUV/RGB formats. */
- if (minFrameDurationNsec > 0) {
- std::vector<int64_t> minFrameDurations;
- minFrameDurations.reserve(streamConfigurations_.size() * 4);
- for (const auto &entry : streamConfigurations_) {
- minFrameDurations.push_back(entry.androidFormat);
- minFrameDurations.push_back(entry.resolution.width);
- minFrameDurations.push_back(entry.resolution.height);
- minFrameDurations.push_back(minFrameDurationNsec);
- }
- staticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
- minFrameDurations);
- }
-
- uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
- staticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE, croppingType);
-
- /* Info static metadata. */
- uint8_t supportedHWLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
- staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
- supportedHWLevel);
-
- /* Request static metadata. */
- int32_t partialResultCount = 1;
- staticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
- partialResultCount);
-
- {
- /* Default the value to 2 if not reported by the camera. */
- uint8_t maxPipelineDepth = 2;
- const auto &infoMap = controlsInfo.find(&controls::draft::PipelineDepth);
- if (infoMap != controlsInfo.end())
- maxPipelineDepth = infoMap->second.max().get<int32_t>();
- staticMetadata_->addEntry(ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
- maxPipelineDepth);
- }
-
- /* LIMITED does not support reprocessing. */
- uint32_t maxNumInputStreams = 0;
- staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
- maxNumInputStreams);
-
- std::vector<uint8_t> availableCapabilities = {
- ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
- };
-
- /* Report if camera supports RAW. */
- bool rawStreamAvailable = false;
- std::unique_ptr<CameraConfiguration> cameraConfig =
- camera_->generateConfiguration({ StreamRole::Raw });
- if (cameraConfig && !cameraConfig->empty()) {
- const PixelFormatInfo &info =
- PixelFormatInfo::info(cameraConfig->at(0).pixelFormat);
- /* Only advertise RAW support if RAW16 is possible. */
- if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW &&
- info.bitsPerPixel == 16) {
- rawStreamAvailable = true;
- availableCapabilities.push_back(ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
- }
- }
-
- /* Number of { RAW, YUV, JPEG } supported output streams */
- int32_t numOutStreams[] = { rawStreamAvailable, 2, 1 };
- staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
- numOutStreams);
-
- staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
- availableCapabilities);
-
- std::vector<int32_t> availableCharacteristicsKeys = {
- ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
- ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
- ANDROID_CONTROL_AE_AVAILABLE_MODES,
- ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
- ANDROID_CONTROL_AE_COMPENSATION_RANGE,
- ANDROID_CONTROL_AE_COMPENSATION_STEP,
- ANDROID_CONTROL_AE_LOCK_AVAILABLE,
- ANDROID_CONTROL_AF_AVAILABLE_MODES,
- ANDROID_CONTROL_AVAILABLE_EFFECTS,
- ANDROID_CONTROL_AVAILABLE_MODES,
- ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
- ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
- ANDROID_CONTROL_AWB_AVAILABLE_MODES,
- ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
- ANDROID_CONTROL_MAX_REGIONS,
- ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
- ANDROID_FLASH_INFO_AVAILABLE,
- ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
- ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
- ANDROID_JPEG_MAX_SIZE,
- ANDROID_LENS_FACING,
- ANDROID_LENS_INFO_AVAILABLE_APERTURES,
- ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
- ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
- ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
- ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
- ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
- ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
- ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
- ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
- ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
- ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
- ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
- ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
- ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
- ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
- ANDROID_SCALER_CROPPING_TYPE,
- ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
- ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
- ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
- ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
- ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
- ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
- ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
- ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
- ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
- ANDROID_SENSOR_ORIENTATION,
- ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
- ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
- ANDROID_SYNC_MAX_LATENCY,
- };
- staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
- availableCharacteristicsKeys);
-
- std::vector<int32_t> availableRequestKeys = {
- ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
- ANDROID_CONTROL_AE_ANTIBANDING_MODE,
- ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
- ANDROID_CONTROL_AE_LOCK,
- ANDROID_CONTROL_AE_MODE,
- ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
- ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
- ANDROID_CONTROL_AF_MODE,
- ANDROID_CONTROL_AF_TRIGGER,
- ANDROID_CONTROL_AWB_LOCK,
- ANDROID_CONTROL_AWB_MODE,
- ANDROID_CONTROL_CAPTURE_INTENT,
- ANDROID_CONTROL_EFFECT_MODE,
- ANDROID_CONTROL_MODE,
- ANDROID_CONTROL_SCENE_MODE,
- ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
- ANDROID_FLASH_MODE,
- ANDROID_JPEG_ORIENTATION,
- ANDROID_JPEG_QUALITY,
- ANDROID_JPEG_THUMBNAIL_QUALITY,
- ANDROID_JPEG_THUMBNAIL_SIZE,
- ANDROID_LENS_APERTURE,
- ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
- ANDROID_NOISE_REDUCTION_MODE,
- ANDROID_SCALER_CROP_REGION,
- ANDROID_STATISTICS_FACE_DETECT_MODE
- };
- staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,
- availableRequestKeys);
-
- std::vector<int32_t> availableResultKeys = {
- ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
- ANDROID_CONTROL_AE_ANTIBANDING_MODE,
- ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
- ANDROID_CONTROL_AE_LOCK,
- ANDROID_CONTROL_AE_MODE,
- ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
- ANDROID_CONTROL_AE_STATE,
- ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
- ANDROID_CONTROL_AF_MODE,
- ANDROID_CONTROL_AF_STATE,
- ANDROID_CONTROL_AF_TRIGGER,
- ANDROID_CONTROL_AWB_LOCK,
- ANDROID_CONTROL_AWB_MODE,
- ANDROID_CONTROL_AWB_STATE,
- ANDROID_CONTROL_CAPTURE_INTENT,
- ANDROID_CONTROL_EFFECT_MODE,
- ANDROID_CONTROL_MODE,
- ANDROID_CONTROL_SCENE_MODE,
- ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
- ANDROID_FLASH_MODE,
- ANDROID_FLASH_STATE,
- ANDROID_JPEG_GPS_COORDINATES,
- ANDROID_JPEG_GPS_PROCESSING_METHOD,
- ANDROID_JPEG_GPS_TIMESTAMP,
- ANDROID_JPEG_ORIENTATION,
- ANDROID_JPEG_QUALITY,
- ANDROID_JPEG_SIZE,
- ANDROID_JPEG_THUMBNAIL_QUALITY,
- ANDROID_JPEG_THUMBNAIL_SIZE,
- ANDROID_LENS_APERTURE,
- ANDROID_LENS_FOCAL_LENGTH,
- ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
- ANDROID_LENS_STATE,
- ANDROID_NOISE_REDUCTION_MODE,
- ANDROID_REQUEST_PIPELINE_DEPTH,
- ANDROID_SCALER_CROP_REGION,
- ANDROID_SENSOR_EXPOSURE_TIME,
- ANDROID_SENSOR_FRAME_DURATION,
- ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,
- ANDROID_SENSOR_TEST_PATTERN_MODE,
- ANDROID_SENSOR_TIMESTAMP,
- ANDROID_STATISTICS_FACE_DETECT_MODE,
- ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
- ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
- ANDROID_STATISTICS_SCENE_FLICKER,
- };
- staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,
- availableResultKeys);
-
- if (!staticMetadata_->isValid()) {
- LOG(HAL, Error) << "Failed to construct static metadata";
- staticMetadata_.reset();
- return nullptr;
- }
-
- if (staticMetadata_->resized()) {
- auto [entryCount, dataCount] = staticMetadata_->usage();
- LOG(HAL, Info)
- << "Static metadata resized: " << entryCount
- << " entries and " << dataCount << " bytes used";
- }
-
- return staticMetadata_->get();
-}
-
-std::unique_ptr<CameraMetadata> CameraDevice::requestTemplatePreview()
+void CameraDevice::setCallbacks(const camera3_callback_ops_t *callbacks)
{
- /*
- * \todo Keep this in sync with the actual number of entries.
- * Currently: 20 entries, 35 bytes
- */
- auto requestTemplate = std::make_unique<CameraMetadata>(21, 36);
- if (!requestTemplate->isValid()) {
- return nullptr;
- }
-
- /* Get the FPS range registered in the static metadata. */
- camera_metadata_ro_entry_t entry;
- bool found = staticMetadata_->getEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
- &entry);
- if (!found) {
- LOG(HAL, Error) << "Cannot create capture template without FPS range";
- return nullptr;
- }
-
- /*
- * Assume the AE_AVAILABLE_TARGET_FPS_RANGE static metadata
- * has been assembled as {{min, max} {max, max}}.
- */
- requestTemplate->addEntry(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
- entry.data.i32, 2);
-
- uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
- requestTemplate->addEntry(ANDROID_CONTROL_AE_MODE, aeMode);
-
- int32_t aeExposureCompensation = 0;
- requestTemplate->addEntry(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
- aeExposureCompensation);
-
- uint8_t aePrecaptureTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;
- requestTemplate->addEntry(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
- aePrecaptureTrigger);
-
- uint8_t aeLock = ANDROID_CONTROL_AE_LOCK_OFF;
- requestTemplate->addEntry(ANDROID_CONTROL_AE_LOCK, aeLock);
-
- uint8_t aeAntibandingMode = ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
- requestTemplate->addEntry(ANDROID_CONTROL_AE_ANTIBANDING_MODE,
- aeAntibandingMode);
-
- uint8_t afMode = ANDROID_CONTROL_AF_MODE_OFF;
- requestTemplate->addEntry(ANDROID_CONTROL_AF_MODE, afMode);
-
- uint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;
- requestTemplate->addEntry(ANDROID_CONTROL_AF_TRIGGER, afTrigger);
-
- uint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO;
- requestTemplate->addEntry(ANDROID_CONTROL_AWB_MODE, awbMode);
-
- uint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;
- requestTemplate->addEntry(ANDROID_CONTROL_AWB_LOCK, awbLock);
-
- uint8_t flashMode = ANDROID_FLASH_MODE_OFF;
- requestTemplate->addEntry(ANDROID_FLASH_MODE, flashMode);
-
- uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
- requestTemplate->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE,
- faceDetectMode);
-
- uint8_t noiseReduction = ANDROID_NOISE_REDUCTION_MODE_OFF;
- requestTemplate->addEntry(ANDROID_NOISE_REDUCTION_MODE,
- noiseReduction);
-
- uint8_t aberrationMode = ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF;
- requestTemplate->addEntry(ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
- aberrationMode);
-
- uint8_t controlMode = ANDROID_CONTROL_MODE_AUTO;
- requestTemplate->addEntry(ANDROID_CONTROL_MODE, controlMode);
-
- float lensAperture = 2.53 / 100;
- requestTemplate->addEntry(ANDROID_LENS_APERTURE, lensAperture);
-
- uint8_t opticalStabilization = ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
- requestTemplate->addEntry(ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
- opticalStabilization);
-
- uint8_t captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
- requestTemplate->addEntry(ANDROID_CONTROL_CAPTURE_INTENT,
- captureIntent);
-
- return requestTemplate;
+ callbacks_ = callbacks;
}
-std::unique_ptr<CameraMetadata> CameraDevice::requestTemplateVideo()
+const camera_metadata_t *CameraDevice::getStaticMetadata()
{
- std::unique_ptr<CameraMetadata> previewTemplate = requestTemplatePreview();
- if (!previewTemplate)
- return nullptr;
-
- /*
- * The video template requires a fixed FPS range. Everything else
- * stays the same as the preview template.
- */
- camera_metadata_ro_entry_t entry;
- staticMetadata_->getEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
- &entry);
-
- /*
- * Assume the AE_AVAILABLE_TARGET_FPS_RANGE static metadata
- * has been assembled as {{min, max} {max, max}}.
- */
- previewTemplate->updateEntry(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
- entry.data.i32 + 2, 2);
-
- return previewTemplate;
+ return capabilities_.staticMetadata()->get();
}
/*
@@ -1630,7 +520,7 @@ const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)
switch (type) {
case CAMERA3_TEMPLATE_PREVIEW:
captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
- requestTemplate = requestTemplatePreview();
+ requestTemplate = capabilities_.requestTemplatePreview();
break;
case CAMERA3_TEMPLATE_STILL_CAPTURE:
/*
@@ -1638,15 +528,15 @@ const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)
* for the torch mode we currently do not support.
*/
captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
- requestTemplate = requestTemplatePreview();
+ requestTemplate = capabilities_.requestTemplatePreview();
break;
case CAMERA3_TEMPLATE_VIDEO_RECORD:
captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
- requestTemplate = requestTemplateVideo();
+ requestTemplate = capabilities_.requestTemplateVideo();
break;
case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT;
- requestTemplate = requestTemplateVideo();
+ requestTemplate = capabilities_.requestTemplateVideo();
break;
/* \todo Implement templates generation for the remaining use cases. */
case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
@@ -1668,19 +558,6 @@ const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)
return requestTemplates_[type]->get();
}
-PixelFormat CameraDevice::toPixelFormat(int format) const
-{
- /* Translate Android format code to libcamera pixel format. */
- auto it = formatsMap_.find(format);
- if (it == formatsMap_.end()) {
- LOG(HAL, Error) << "Requested format " << utils::hex(format)
- << " not supported";
- return PixelFormat();
- }
-
- return it->second;
-}
-
/*
* Inspect the stream_list to produce a list of StreamConfiguration to
* be use to configure the Camera.
@@ -1727,7 +604,7 @@ int CameraDevice::configureStreams(camera3_stream_configuration_t *stream_list)
camera3_stream_t *stream = stream_list->streams[i];
Size size(stream->width, stream->height);
- PixelFormat format = toPixelFormat(stream->format);
+ PixelFormat format = capabilities_.toPixelFormat(stream->format);
LOG(HAL, Info) << "Stream #" << i
<< ", direction: " << stream->stream_type
diff --git a/src/android/camera_device.h b/src/android/camera_device.h
index 4aadb27c..090fe28a 100644
--- a/src/android/camera_device.h
+++ b/src/android/camera_device.h
@@ -10,14 +10,12 @@
#include <map>
#include <memory>
#include <mutex>
-#include <tuple>
#include <vector>
#include <hardware/camera3.h>
#include <libcamera/buffer.h>
#include <libcamera/camera.h>
-#include <libcamera/geometry.h>
#include <libcamera/request.h>
#include <libcamera/stream.h>
@@ -26,6 +24,7 @@
#include "libcamera/internal/message.h"
#include "libcamera/internal/thread.h"
+#include "camera_capabilities.h"
#include "camera_metadata.h"
#include "camera_stream.h"
#include "camera_worker.h"
@@ -57,7 +56,7 @@ public:
const std::string &model() const { return model_; }
int facing() const { return facing_; }
int orientation() const { return orientation_; }
- unsigned int maxJpegBufferSize() const { return maxJpegBufferSize_; }
+ unsigned int maxJpegBufferSize() const;
void setCallbacks(const camera3_callback_ops_t *callbacks);
const camera_metadata_t *getStaticMetadata();
@@ -86,11 +85,6 @@ private:
std::unique_ptr<CaptureRequest> request_;
};
- struct Camera3StreamConfiguration {
- libcamera::Size resolution;
- int androidFormat;
- };
-
enum class State {
Stopped,
Flushing,
@@ -99,22 +93,11 @@ private:
void stop();
- int initializeStreamConfigurations();
- std::vector<libcamera::Size>
- getYUVResolutions(libcamera::CameraConfiguration *cameraConfig,
- const libcamera::PixelFormat &pixelFormat,
- const std::vector<libcamera::Size> &resolutions);
- std::vector<libcamera::Size>
- getRawResolutions(const libcamera::PixelFormat &pixelFormat);
-
libcamera::FrameBuffer *createFrameBuffer(const buffer_handle_t camera3buffer);
void abortRequest(camera3_capture_request_t *request);
void notifyShutter(uint32_t frameNumber, uint64_t timestamp);
void notifyError(uint32_t frameNumber, camera3_stream_t *stream,
camera3_error_msg_code code);
- std::unique_ptr<CameraMetadata> requestTemplatePreview();
- std::unique_ptr<CameraMetadata> requestTemplateVideo();
- libcamera::PixelFormat toPixelFormat(int format) const;
int processControls(Camera3RequestDescriptor *descriptor);
std::unique_ptr<CameraMetadata> getResultMetadata(
const Camera3RequestDescriptor &descriptor) const;
@@ -129,13 +112,11 @@ private:
std::shared_ptr<libcamera::Camera> camera_;
std::unique_ptr<libcamera::CameraConfiguration> config_;
+ CameraCapabilities capabilities_;
- std::unique_ptr<CameraMetadata> staticMetadata_;
std::map<unsigned int, std::unique_ptr<CameraMetadata>> requestTemplates_;
const camera3_callback_ops_t *callbacks_;
- std::vector<Camera3StreamConfiguration> streamConfigurations_;
- std::map<int, libcamera::PixelFormat> formatsMap_;
std::vector<CameraStream> streams_;
libcamera::Mutex descriptorsMutex_; /* Protects descriptors_. */
@@ -147,8 +128,6 @@ private:
int facing_;
int orientation_;
- unsigned int maxJpegBufferSize_;
-
CameraMetadata lastSettings_;
};
diff --git a/src/android/meson.build b/src/android/meson.build
index f27fd531..6270fb20 100644
--- a/src/android/meson.build
+++ b/src/android/meson.build
@@ -44,6 +44,7 @@ subdir('cros')
android_hal_sources = files([
'camera3_hal.cpp',
+ 'camera_capabilities.cpp',
'camera_device.cpp',
'camera_hal_config.cpp',
'camera_hal_manager.cpp',