[libcamera-devel] [RFC PATCH v2 05/12] android: camera_device: Set static metadata for FULL requirements

Jacopo Mondi jacopo at jmondi.org
Tue Apr 27 10:15:41 CEST 2021


Hi Paul,

On Thu, Apr 22, 2021 at 06:40:55PM +0900, Paul Elder wrote:
> Set the static metadata as required by CTS for FULL hardware level.
>
> The tests that this fixes are:
> android.hardware.camera2.cts.StaticMetadataTest#testHwSupportedLevel
>
> Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
>
> ---
> This patch actually introduces more failures in CTS, but that's because
> we report that we support many more things in the static metadata.
>
> The main thing I'm not sure of in this patch is if the entries in any
> AVAILABLE_* tags require allocated space in the static metadata. Also
> the android docs say that they need to be int32_t while CTS (and other
> HAL implementations) say that they need to be uint8_t.
> ---
>  src/android/camera_device.cpp | 148 +++++++++++++++++++++++++++++++---
>  1 file changed, 139 insertions(+), 9 deletions(-)
>
> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
> index a11ad848..7f0f8f1a 100644
> --- a/src/android/camera_device.cpp
> +++ b/src/android/camera_device.cpp
> @@ -776,10 +776,19 @@ std::tuple<uint32_t, uint32_t> CameraDevice::calculateStaticMetadataSize()
>  {
>  	/*
>  	 * \todo Keep this in sync with the actual number of entries.
> -	 * Currently: 54 entries, 874 bytes of static metadata
> +	 * Currently: 63 entries, 990 bytes of static metadata
>  	 */
> -	uint32_t numEntries = 54;
> -	uint32_t byteSize = 874;
> +	uint32_t numEntries = 63;
> +	uint32_t byteSize = 990;
> +
> +	// do i need to add for entries in the available keys?
> +	// +1, +4 for EDGE_AVAILABLE_EDGE_MODES
> +	// +1, +4 for LENS_INFO_AVAILABLE_FILTER_DENSITIES
> +	// +1, +4 for BLACK_LEVEL_PATTERN
> +	// +1, +4 for TONEMAP_AVAILABLE_TONE_MAP_MODES
> +	// +1, +4 for TONEMAP_MAX_CURVE_POINTS

For each new tag you add in availableCharacteristicsKeys is +4, for
new value associated with an existing or a new tag, it depends which
type the tag accepts

I've not validated the above calculations yet


> +
> +	// +36 for new request keys
>
>  	/*
>  	 * Calculate space occupation in bytes for dynamically built metadata
> @@ -861,7 +870,9 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>  				  aeAvailableAntiBandingModes.data(),
>  				  aeAvailableAntiBandingModes.size());
>
> +	/* \todo FULL requires OFF */
>  	std::vector<uint8_t> aeAvailableModes = {
> +		ANDROID_CONTROL_AE_MODE_OFF,

+1

>  		ANDROID_CONTROL_AE_MODE_ON,
>  	};
>  	staticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,
> @@ -958,9 +969,11 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>
>  	/*
>  	 * \todo Inspect the Camera capabilities to report the available
> -	 * AWB modes. Default to AUTO as CTS tests require it.
> +	 * AWB modes. Default to AUTO as CTS tests require it. FULL requires
> +	 * OFF.
>  	 */
>  	std::vector<uint8_t> availableAwbModes = {
> +		ANDROID_CONTROL_AWB_MODE_OFF,

+1

I wonder if it is correct to make this unconditional.
The drawback is that it requires an IPA and requires the PH to
register property correctly. If for the IPU3 we have that, I would
fetch this information from the Camera.

>  		ANDROID_CONTROL_AWB_MODE_AUTO,
>  	};
>  	staticMetadata_->addEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES,
> @@ -983,17 +996,32 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>  				  sceneModesOverride.data(),
>  				  sceneModesOverride.size());
>
> -	uint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
> +	/* true for MANUAL_SENSOR or BURST_CAPTURE capable devices */
> +	uint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE;
>  	staticMetadata_->addEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,
>  				  &aeLockAvailable, 1);

Again, should this come from the camera ?

>
> -	uint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
> +	/* true for MANUAL_SENSOR or BURST_CAPTURE capable devices */
> +	uint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE;
>  	staticMetadata_->addEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
>  				  &awbLockAvailable, 1);

ditto

>
>  	char availableControlModes = ANDROID_CONTROL_MODE_AUTO;
>  	staticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES,
>  				  &availableControlModes, 1);
> +	/*
> +	 * FULL - always support OFF
> +	 * camera devices that support YUV_REPROCESSING or PRIVATE_REPROCESSING - ZERO_SHUTTER_LAG
> +	 * all devices will list FAST
> +	 */
> +	std::vector<uint8_t> availableEdgeModes = {
> +		ANDROID_EDGE_MODE_OFF,
> +		ANDROID_EDGE_MODE_FAST,
> +		ANDROID_EDGE_MODE_HIGH_QUALITY,
> +	};

+3

> +	staticMetadata_->addEntry(ANDROID_EDGE_AVAILABLE_EDGE_MODES,
> +				  availableEdgeModes.data(),
> +				  availableEdgeModes.size());

Edging I'm not sure we have it from Camera

>
>  	/* JPEG static metadata. */
>
> @@ -1079,10 +1107,20 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>  			exposureInfo->second.min().get<int32_t>() * 1000LL,
>  			exposureInfo->second.max().get<int32_t>() * 1000LL,
>  		};
> +		/* min must be at most 100us, max at least 100ms */
> +		if (exposureTimeRange[0] > 100000)
> +			exposureTimeRange[0] = 100000;
> +		if (exposureTimeRange[1] < 100000000)
> +			exposureTimeRange[1] = 100000000;

Underated and probably worth a separate patch ?

>  		staticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
>  					  &exposureTimeRange, 2);
>  	}
>
> +	/* min at most 100, max at least 800 */
> +	int32_t maxAnalogSensitivity = 800;
> +	staticMetadata_->addEntry(ANDROID_SENSOR_MAX_ANALOG_SENSITIVITY,
> +				  &maxAnalogSensitivity, 1);

+4

An information for the sensor database ?
Also, we might want a draft control, and plum this from the db, to the
pipeline handler, to the HAL

> +

empty line not required

>  	staticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION, &orientation_, 1);


>
>  	std::vector<int32_t> testPatterModes = {
> @@ -1092,6 +1130,21 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>  				  testPatterModes.data(),
>  				  testPatterModes.size());
>
> +	/*
> +	 * required for FULL (docs don't say it is, but cts says it is)
> +	 * \todo figure out how this works
> +	 */
> +	std::vector<int32_t> blackLevelPattern = { 0, 0, 0, 0 };

+16

> +	staticMetadata_->addEntry(ANDROID_SENSOR_BLACK_LEVEL_PATTERN,
> +				  blackLevelPattern.data(),
> +				  blackLevelPattern.size());
> +
> +	/* range of valid values: > 255 (8-bit output) */
> +	/* this xnor BLACK_LEVEL_PATTERN must be available */
> +	int32_t whiteLevel = 256;

+4

> +	staticMetadata_->addEntry(ANDROID_SENSOR_INFO_WHITE_LEVEL,
> +				  &whiteLevel, 1);
> +

I'm not sure where these info should come from

>  	std::vector<float> physicalSize = {
>  		2592, 1944,
>  	};
> @@ -1131,7 +1184,7 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>  	}
>
>  	/* Sync static metadata. */
> -	int32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
> +	int32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_PER_FRAME_CONTROL;

This is an hard statement to make :)

>  	staticMetadata_->addEntry(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);
>
>  	/* Flash static metadata. */
> @@ -1147,6 +1200,15 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>  				  lensApertures.data(),
>  				  lensApertures.size());
>
> +	/*
> +	 * Required for FULL
> +	 * \todo get this information from the camera, in ascending order
> +	 */
> +	std::vector<float> availableFilterDensities = { 0 };

+4

> +	staticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES,
> +				  availableFilterDensities.data(),
> +				  availableFilterDensities.size());
> +

Lens info should come from the ConfigurationFile. Add a \todo maybe ?
>  	uint8_t lensFacing;
>  	switch (facing_) {
>  	default:
> @@ -1176,6 +1238,11 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>  				  opticalStabilizations.data(),
>  				  opticalStabilizations.size());
>
> +	/* \todo set this based on camera capability */

Or configuration file

> +	int distanceCalibration = ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE;

it's a BYTE

> +	staticMetadata_->addEntry(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
> +				  &distanceCalibration, 1);
> +
>  	float hypeFocalDistance = 0;
>  	staticMetadata_->addEntry(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
>  				  &hypeFocalDistance, 1);
> @@ -1188,12 +1255,18 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>  	{
>  		std::vector<uint8_t> data;
>  		data.reserve(5);
> +		/*
> +		 * \todo if this doesn't have OFF and FAST and HIGH_QUALITY
> +		 * then this camera does not support FULL
> +		 */
>  		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);
> +			data.push_back(ANDROID_NOISE_REDUCTION_MODE_FAST);
> +			data.push_back(ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY);
>  		}
>  		staticMetadata_->addEntry(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
>  					  data.data(), data.size());
> @@ -1261,6 +1334,16 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>  	uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
>  	staticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);
>
> +	/* \todo figure out if this should be int32 as documented */

doc says byte x n
> +	std::vector<uint8_t> shadingAvailableModes = {
> +		ANDROID_SHADING_MODE_OFF,
> +		ANDROID_SHADING_MODE_FAST,
> +		ANDROID_SHADING_MODE_HIGH_QUALITY,
> +	};

So +3

> +	staticMetadata_->addEntry(ANDROID_SHADING_AVAILABLE_MODES,
> +				  shadingAvailableModes.data(),
> +				  shadingAvailableModes.size());
> +
>  	/* Info static metadata. */
>  	uint8_t supportedHWLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL;
>  	staticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
> @@ -1288,6 +1371,10 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>
>  	std::vector<uint8_t> availableCapabilities = {
>  		ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
> +		ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR,
> +		ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING,
> +		ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS,
> +		ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE,

Are all of these required for FULL mode ?

>  	};
>
>  	/* Report if camera supports RAW. */
> @@ -1306,7 +1393,7 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>  	}
>
>  	/* Number of { RAW, YUV, JPEG } supported output streams */
> -	int32_t numOutStreams[] = { rawStreamAvailable, 2, 1 };
> +	int32_t numOutStreams[] = { rawStreamAvailable, 3, 1 };

We should do a little more than just bumping this number up to claim
this :)

>  	staticMetadata_->addEntry(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
>  				  &numOutStreams, 3);
>
> @@ -1314,6 +1401,29 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>  				  availableCapabilities.data(),
>  				  availableCapabilities.size());
>
> +	/*
> +	 * required for FULL
> +	 * at least one of the below mode combinations:
> +	 * - CONTRAST_CURVE, FAST, HIGH_QUALITY
> +	 * - GAMMA_VALUE, PRESET_CURVE, FAST, HIGH_QUALITY
> +	 */
> +	std::vector<uint8_t> availableTonemapModes = {
> +		ANDROID_TONEMAP_MODE_CONTRAST_CURVE,
> +		ANDROID_TONEMAP_MODE_FAST,
> +		ANDROID_TONEMAP_MODE_HIGH_QUALITY,
> +	};
> +	staticMetadata_->addEntry(ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES,
> +				  availableTonemapModes.data(),
> +				  availableTonemapModes.size());

I'm sincerely not sure where these info sould come from

> +
> +	/*
> +	 * required for FULL
> +	 * \todo get from camera (camCapabilities[camId]->tonemapCurvePoints?)
> +	 */
> +	int32_t tonemapCurvePoints = 0;
> +	staticMetadata_->addEntry(ANDROID_TONEMAP_MAX_CURVE_POINTS,
> +				  &tonemapCurvePoints, 1);
> +
>  	std::vector<int32_t> availableCharacteristicsKeys = {
>  		ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
>  		ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
> @@ -1331,14 +1441,17 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>  		ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
>  		ANDROID_CONTROL_MAX_REGIONS,
>  		ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
> +		ANDROID_EDGE_AVAILABLE_EDGE_MODES,
>  		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_FILTER_DENSITIES,
>  		ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
>  		ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
> +		ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
>  		ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
>  		ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
>  		ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
> @@ -1353,6 +1466,7 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>  		ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
>  		ANDROID_SCALER_CROPPING_TYPE,
>  		ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
> +		ANDROID_SENSOR_BLACK_LEVEL_PATTERN,
>  		ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
>  		ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
>  		ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
> @@ -1361,17 +1475,25 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>  		ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
>  		ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
>  		ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
> +		ANDROID_SENSOR_INFO_WHITE_LEVEL,
> +		ANDROID_SENSOR_MAX_ANALOG_SENSITIVITY,
>  		ANDROID_SENSOR_ORIENTATION,
> +		ANDROID_SHADING_AVAILABLE_MODES,
>  		ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
>  		ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
>  		ANDROID_SYNC_MAX_LATENCY,
> +		ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES,
> +		ANDROID_TONEMAP_MAX_CURVE_POINTS,

Each new one is +4

>  	};
>  	staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
>  				  availableCharacteristicsKeys.data(),
>  				  availableCharacteristicsKeys.size());
>
>  	std::vector<int32_t> availableRequestKeys = {
> +		ANDROID_BLACK_LEVEL_LOCK,
>  		ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
> +		ANDROID_COLOR_CORRECTION_GAINS,
> +		ANDROID_COLOR_CORRECTION_TRANSFORM,
>  		ANDROID_CONTROL_AE_ANTIBANDING_MODE,
>  		ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
>  		ANDROID_CONTROL_AE_LOCK,
> @@ -1387,16 +1509,24 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
>  		ANDROID_CONTROL_MODE,
>  		ANDROID_CONTROL_SCENE_MODE,
>  		ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
> +		ANDROID_EDGE_MODE,
>  		ANDROID_FLASH_MODE,
>  		ANDROID_JPEG_ORIENTATION,
>  		ANDROID_JPEG_QUALITY,
>  		ANDROID_JPEG_THUMBNAIL_QUALITY,
>  		ANDROID_JPEG_THUMBNAIL_SIZE,
>  		ANDROID_LENS_APERTURE,
> +		ANDROID_LENS_FILTER_DENSITY,
>  		ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
>  		ANDROID_NOISE_REDUCTION_MODE,
>  		ANDROID_SCALER_CROP_REGION,
> -		ANDROID_STATISTICS_FACE_DETECT_MODE
> +		ANDROID_SENSOR_EXPOSURE_TIME,
> +		ANDROID_SENSOR_FRAME_DURATION,
> +		ANDROID_SENSOR_SENSITIVITY,
> +		ANDROID_SHADING_MODE,
> +		ANDROID_STATISTICS_FACE_DETECT_MODE,
> +		ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
> +		ANDROID_TONEMAP_MODE,

I've done this multiple time, but I'll just re-state that we're
claiming support for controls without actually handling them

Thanks
   j
>  	};

>  	staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,
>  				  availableRequestKeys.data(),
> --
> 2.27.0
>
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel


More information about the libcamera-devel mailing list