[libcamera-devel] [PATCH 2/2] android: Introduce CameraCapabilties class
Hirokazu Honda
hiroh at chromium.org
Wed Jun 23 05:25:01 CEST 2021
Hi Jacopo,
On Tue, Jun 22, 2021 at 4:40 PM Jacopo Mondi <jacopo at jmondi.org> wrote:
>
> Hi Hiro,
>
> On Tue, Jun 22, 2021 at 10:34:27AM +0900, Hirokazu Honda wrote:
> > Hi Jacopo, thank you for the patch.
> >
> > I failed to apply the patch on the top of the latest tree to review.
> > Could you tell me the parent commit which I can apply this patch?
>
> weird, I just applied these two patches cleanly on the latest
> master which for me is
> 969da3189439 ("libcamera: utils: Support systems that lack secure_getenv and issetugid"
>
I tried applying the series whose id is 2162. But the series doesn't
contain "[PATCH 1/2] android: Sort source files alphabetically".
In fact, the patch is not shown in patchwork. It is strange.
I managed to apply this patch after manually applying 1/2.
>
> >
> > -Hiro
> > On Tue, Jun 22, 2021 at 12:29 AM Jacopo Mondi <jacopo at jmondi.org> wrote:
> >
> > > 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 relative to:
> > > - Initialization of supported stream configurations
> > > - Initialization of static metadata
> > > - Initialization of request templates
> > >
> > > Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
> > > Acked-by: Paul Elder <paul.elder at ideasonboard.com>
> > > Tested-by: Paul Elder <paul.elder at ideasonboard.com>
> > > ---
> > > src/android/camera_capabilities.cpp | 1164 +++++++++++++++++++++++++++
> > > src/android/camera_capabilities.h | 65 ++
> > > src/android/camera_device.cpp | 1147 +-------------------------
> > > src/android/camera_device.h | 27 +-
> > > src/android/meson.build | 1 +
> > > 5 files changed, 1245 insertions(+), 1159 deletions(-)
> > > create mode 100644 src/android/camera_capabilities.cpp
> > > create mode 100644 src/android/camera_capabilities.h
> > >
> > > diff --git a/src/android/camera_capabilities.cpp
> > > b/src/android/camera_capabilities.cpp
> > > new file mode 100644
> > > index 000000000000..311a2c839586
> > > --- /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 000000000000..f511607bbd90
> > > --- /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 8c71fd0675d3..4bd125d7020a 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"
> > > @@ -36,94 +32,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)
> > > @@ -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 4aadb27c562c..090fe28a551e 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 f27fd5316705..6270fb201338 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',
Since the code is copied as-is,
Reviewed-by: Hirokazu Honda <hiroh at chromium.org>
Although stylecheck script complains some part of code, do you think fixing it?
-Hiro
> > > --
> > > 2.31.1
> > >
> > >
More information about the libcamera-devel
mailing list