From 4bb81dfcc4a7d2134986bb64b733c41388b8060d Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Sat, 19 Jun 2021 12:10:54 +0200 Subject: android: Introduce CameraCapabilties class The camera_device.cpp has grown a little too much, and it has quickly become hard to maintain. Break out the handling of the static information collected at camera initialization time to a new CameraCapabilities class. Break out from the camera_device.cpp file all the functions related to: - Initialization of supported stream configurations - Initialization of static metadata - Initialization of request templates Signed-off-by: Jacopo Mondi Acked-by: Paul Elder Tested-by: Paul Elder Reviewed-by: Laurent Pinchart Reviewed-by: Hirokazu Honda --- 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 (limited to 'src') diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp new file mode 100644 index 00000000..00224a6d --- /dev/null +++ b/src/android/camera_capabilities.cpp @@ -0,0 +1,1164 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google Inc. + * + * camera_capabilities.cpp - Camera static properties manager + */ + +#include "camera_capabilities.h" + +#include +#include + +#include + +#include +#include +#include + +#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 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 libcameraFormats; + bool mandatory; + const char *name; +}; + +/* + * \var camera3FormatsMap + * \brief Associate Android format code with ancillary data + */ +const std::map 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 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 CameraCapabilities::getYUVResolutions(CameraConfiguration *cameraConfig, + const PixelFormat &pixelFormat, + const std::vector &resolutions) +{ + std::vector 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 CameraCapabilities::getRawResolutions(const libcamera::PixelFormat &pixelFormat) +{ + std::unique_ptr cameraConfig = + camera_->generateConfiguration({ StreamRole::Raw }); + StreamConfiguration &cfg = cameraConfig->at(0); + const StreamFormats &formats = cfg.formats(); + std::vector 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 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 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 &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 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(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 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()); + } else { + data.push_back(ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF); + } + staticMetadata_->addEntry(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, + data); + } + + /* Control static metadata. */ + std::vector 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 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() * 1000; + maxFrameDurationNsec = frameDurationsInfo->second.max().get() * 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 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 availableAfModes = { + ANDROID_CONTROL_AF_MODE_OFF, + }; + staticMetadata_->addEntry(ANDROID_CONTROL_AF_AVAILABLE_MODES, + availableAfModes); + + std::vector availableEffects = { + ANDROID_CONTROL_EFFECT_MODE_OFF, + }; + staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_EFFECTS, + availableEffects); + + std::vector availableSceneModes = { + ANDROID_CONTROL_SCENE_MODE_DISABLED, + }; + staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, + availableSceneModes); + + std::vector 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 availableAwbModes = { + ANDROID_CONTROL_AWB_MODE_AUTO, + }; + staticMetadata_->addEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES, + availableAwbModes); + + std::vector availableMaxRegions = { + 0, 0, 0, + }; + staticMetadata_->addEntry(ANDROID_CONTROL_MAX_REGIONS, + availableMaxRegions); + + std::vector 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 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 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 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(properties::UnitCellSize); + std::array physicalSize{ + cellSize.width * pixelArraySize[0] / 1e6f, + cellSize.height * pixelArraySize[1] / 1e6f + }; + staticMetadata_->addEntry(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, + physicalSize); + } + + { + const Span &rects = + properties.get(properties::PixelArrayActiveAreas); + std::vector data{ + static_cast(rects[0].x), + static_cast(rects[0].y), + static_cast(rects[0].width), + static_cast(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() * 1000LL, + exposureInfo->second.max().get() * 1000LL, + }; + staticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE, + exposureTimeRange, 2); + } + + staticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION, orientation_); + + std::vector 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()) { + 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(); + 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 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()); + } 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 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 lensFocalLengths = { + 1, + }; + staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, + lensFocalLengths); + + std::vector 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 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()); + } 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 max = scalerCrop->second.max().get(); + 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 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 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 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(); + 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 availableCapabilities = { + ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE, + }; + + /* Report if camera supports RAW. */ + bool rawStreamAvailable = false; + std::unique_ptr 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 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 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 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 CameraCapabilities::requestTemplatePreview() const +{ + /* + * \todo Keep this in sync with the actual number of entries. + * Currently: 20 entries, 35 bytes + */ + auto requestTemplate = std::make_unique(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 CameraCapabilities::requestTemplateVideo() const +{ + std::unique_ptr previewTemplate = requestTemplatePreview(); + if (!previewTemplate) + return nullptr; + + /* + * The video template requires a fixed FPS range. Everything else + * stays the same as the preview template. + */ + camera_metadata_ro_entry_t entry; + staticMetadata_->getEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, + &entry); + + /* + * Assume the AE_AVAILABLE_TARGET_FPS_RANGE static metadata + * has been assembled as {{min, max} {max, max}}. + */ + previewTemplate->updateEntry(ANDROID_CONTROL_AE_TARGET_FPS_RANGE, + entry.data.i32 + 2, 2); + + return previewTemplate; +} diff --git a/src/android/camera_capabilities.h b/src/android/camera_capabilities.h new file mode 100644 index 00000000..f511607b --- /dev/null +++ b/src/android/camera_capabilities.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google Inc. + * + * camera_capabilities.h - Camera static properties manager + */ +#ifndef __ANDROID_CAMERA_CAPABILITIES_H__ +#define __ANDROID_CAMERA_CAPABILITIES_H__ + +#include +#include +#include + +#include +#include +#include +#include + +#include "camera_metadata.h" + +class CameraCapabilities +{ +public: + CameraCapabilities() = default; + + int initialize(std::shared_ptr 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 requestTemplatePreview() const; + std::unique_ptr requestTemplateVideo() const; + +private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraCapabilities) + + struct Camera3StreamConfiguration { + libcamera::Size resolution; + int androidFormat; + }; + + std::vector + getYUVResolutions(libcamera::CameraConfiguration *cameraConfig, + const libcamera::PixelFormat &pixelFormat, + const std::vector &resolutions); + std::vector + getRawResolutions(const libcamera::PixelFormat &pixelFormat); + int initializeStreamConfigurations(); + + int initializeStaticMetadata(); + + std::shared_ptr camera_; + + int facing_; + int orientation_; + + std::vector streamConfigurations_; + std::map formatsMap_; + std::unique_ptr staticMetadata_; + unsigned int maxJpegBufferSize_; +}; + +#endif /* __ANDROID_CAMERA_CAPABILITIES_H__ */ diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp index 8c71fd06..4bd125d7 100644 --- a/src/android/camera_device.cpp +++ b/src/android/camera_device.cpp @@ -10,11 +10,8 @@ #include "camera_ops.h" #include "post_processor.h" -#include -#include #include #include -#include #include #include @@ -23,7 +20,6 @@ #include #include -#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 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 libcameraFormats; - bool mandatory; - const char *name; -}; - -/* - * \var camera3FormatsMap - * \brief Associate Android format code with ancillary data - */ -const std::map 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 CameraDevice::getYUVResolutions(CameraConfiguration *cameraConfig, - const PixelFormat &pixelFormat, - const std::vector &resolutions) -{ - std::vector 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 CameraDevice::getRawResolutions(const libcamera::PixelFormat &pixelFormat) -{ - std::unique_ptr cameraConfig = - camera_->generateConfiguration({ StreamRole::Raw }); - StreamConfiguration &cfg = cameraConfig->at(0); - const StreamFormats &formats = cfg.formats(); - std::vector 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 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 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 &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 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(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 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()); - } else { - data.push_back(ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF); - } - staticMetadata_->addEntry(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, - data); - } - - /* Control static metadata. */ - std::vector 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 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() * 1000; - maxFrameDurationNsec = frameDurationsInfo->second.max().get() * 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 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 availableAfModes = { - ANDROID_CONTROL_AF_MODE_OFF, - }; - staticMetadata_->addEntry(ANDROID_CONTROL_AF_AVAILABLE_MODES, - availableAfModes); - - std::vector availableEffects = { - ANDROID_CONTROL_EFFECT_MODE_OFF, - }; - staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_EFFECTS, - availableEffects); - - std::vector availableSceneModes = { - ANDROID_CONTROL_SCENE_MODE_DISABLED, - }; - staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, - availableSceneModes); - - std::vector 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 availableAwbModes = { - ANDROID_CONTROL_AWB_MODE_AUTO, - }; - staticMetadata_->addEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES, - availableAwbModes); - - std::vector availableMaxRegions = { - 0, 0, 0, - }; - staticMetadata_->addEntry(ANDROID_CONTROL_MAX_REGIONS, - availableMaxRegions); - - std::vector 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 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 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 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(properties::UnitCellSize); - std::array physicalSize{ - cellSize.width * pixelArraySize[0] / 1e6f, - cellSize.height * pixelArraySize[1] / 1e6f - }; - staticMetadata_->addEntry(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, - physicalSize); - } - - { - const Span &rects = - properties.get(properties::PixelArrayActiveAreas); - std::vector data{ - static_cast(rects[0].x), - static_cast(rects[0].y), - static_cast(rects[0].width), - static_cast(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() * 1000LL, - exposureInfo->second.max().get() * 1000LL, - }; - staticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE, - exposureTimeRange, 2); - } - - staticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION, orientation_); - - std::vector 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()) { - 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(); - 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 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()); - } 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 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 lensFocalLengths = { - 1, - }; - staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, - lensFocalLengths); - - std::vector 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 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()); - } 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 max = scalerCrop->second.max().get(); - 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 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 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 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(); - 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 availableCapabilities = { - ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE, - }; - - /* Report if camera supports RAW. */ - bool rawStreamAvailable = false; - std::unique_ptr 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 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 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 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 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(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 CameraDevice::requestTemplateVideo() +const camera_metadata_t *CameraDevice::getStaticMetadata() { - std::unique_ptr previewTemplate = requestTemplatePreview(); - if (!previewTemplate) - return nullptr; - - /* - * The video template requires a fixed FPS range. Everything else - * stays the same as the preview template. - */ - camera_metadata_ro_entry_t entry; - staticMetadata_->getEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, - &entry); - - /* - * Assume the AE_AVAILABLE_TARGET_FPS_RANGE static metadata - * has been assembled as {{min, max} {max, max}}. - */ - previewTemplate->updateEntry(ANDROID_CONTROL_AE_TARGET_FPS_RANGE, - entry.data.i32 + 2, 2); - - return previewTemplate; + return capabilities_.staticMetadata()->get(); } /* @@ -1630,7 +520,7 @@ const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type) switch (type) { case CAMERA3_TEMPLATE_PREVIEW: captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW; - requestTemplate = requestTemplatePreview(); + requestTemplate = capabilities_.requestTemplatePreview(); break; case CAMERA3_TEMPLATE_STILL_CAPTURE: /* @@ -1638,15 +528,15 @@ const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type) * for the torch mode we currently do not support. */ captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE; - requestTemplate = requestTemplatePreview(); + requestTemplate = capabilities_.requestTemplatePreview(); break; case CAMERA3_TEMPLATE_VIDEO_RECORD: captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD; - requestTemplate = requestTemplateVideo(); + requestTemplate = capabilities_.requestTemplateVideo(); break; case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT: captureIntent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT; - requestTemplate = requestTemplateVideo(); + requestTemplate = capabilities_.requestTemplateVideo(); break; /* \todo Implement templates generation for the remaining use cases. */ case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG: @@ -1668,19 +558,6 @@ const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type) return requestTemplates_[type]->get(); } -PixelFormat CameraDevice::toPixelFormat(int format) const -{ - /* Translate Android format code to libcamera pixel format. */ - auto it = formatsMap_.find(format); - if (it == formatsMap_.end()) { - LOG(HAL, Error) << "Requested format " << utils::hex(format) - << " not supported"; - return PixelFormat(); - } - - return it->second; -} - /* * Inspect the stream_list to produce a list of StreamConfiguration to * be use to configure the Camera. @@ -1727,7 +604,7 @@ int CameraDevice::configureStreams(camera3_stream_configuration_t *stream_list) camera3_stream_t *stream = stream_list->streams[i]; Size size(stream->width, stream->height); - PixelFormat format = toPixelFormat(stream->format); + PixelFormat format = capabilities_.toPixelFormat(stream->format); LOG(HAL, Info) << "Stream #" << i << ", direction: " << stream->stream_type diff --git a/src/android/camera_device.h b/src/android/camera_device.h index 4aadb27c..090fe28a 100644 --- a/src/android/camera_device.h +++ b/src/android/camera_device.h @@ -10,14 +10,12 @@ #include #include #include -#include #include #include #include #include -#include #include #include @@ -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 request_; }; - struct Camera3StreamConfiguration { - libcamera::Size resolution; - int androidFormat; - }; - enum class State { Stopped, Flushing, @@ -99,22 +93,11 @@ private: void stop(); - int initializeStreamConfigurations(); - std::vector - getYUVResolutions(libcamera::CameraConfiguration *cameraConfig, - const libcamera::PixelFormat &pixelFormat, - const std::vector &resolutions); - std::vector - 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 requestTemplatePreview(); - std::unique_ptr requestTemplateVideo(); - libcamera::PixelFormat toPixelFormat(int format) const; int processControls(Camera3RequestDescriptor *descriptor); std::unique_ptr getResultMetadata( const Camera3RequestDescriptor &descriptor) const; @@ -129,13 +112,11 @@ private: std::shared_ptr camera_; std::unique_ptr config_; + CameraCapabilities capabilities_; - std::unique_ptr staticMetadata_; std::map> requestTemplates_; const camera3_callback_ops_t *callbacks_; - std::vector streamConfigurations_; - std::map formatsMap_; std::vector streams_; libcamera::Mutex descriptorsMutex_; /* Protects descriptors_. */ @@ -147,8 +128,6 @@ private: int facing_; int orientation_; - unsigned int maxJpegBufferSize_; - CameraMetadata lastSettings_; }; diff --git a/src/android/meson.build b/src/android/meson.build index f27fd531..6270fb20 100644 --- a/src/android/meson.build +++ b/src/android/meson.build @@ -44,6 +44,7 @@ subdir('cros') android_hal_sources = files([ 'camera3_hal.cpp', + 'camera_capabilities.cpp', 'camera_device.cpp', 'camera_hal_config.cpp', 'camera_hal_manager.cpp', -- cgit v1.2.1