diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h index 8af3c7cc57..5db46152b2 100644 --- a/camera/ndk/include/camera/NdkCameraMetadataTags.h +++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h @@ -3288,6 +3288,81 @@ typedef enum acamera_metadata_tag { */ ACAMERA_SCALER_CROPPING_TYPE = // byte (acamera_metadata_enum_android_scaler_cropping_type_t) ACAMERA_SCALER_START + 13, + /** + *

Recommended stream configurations for common client use cases.

+ * + *

Type: int32[n*5] (acamera_metadata_enum_android_scaler_available_recommended_stream_configurations_t)

+ * + *

This tag may appear in: + *

+ * + *

Optional subset of the ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS that contains + * similar tuples listed as + * (i.e. width, height, format, output/input stream, usecase bit field). + * Camera devices will be able to suggest particular stream configurations which are + * power and performance efficient for specific use cases. For more information about + * retrieving the suggestions see + * CameraCharacteristics#getRecommendedStreamConfigurationMap.

+ *

The data representation is int[5], which maps to + * (width, height, format, output/input stream, usecase bit field). The array can be + * parsed using the following pseudo code:

+ *

struct StreamConfiguration { + * int32_t format; + * int32_t width; + * int32_t height; + * int32_t isInput; };

+ *

void getPreferredStreamConfigurations( + * int32_t *array, size_t count, int32_t usecaseId, + * Vector < StreamConfiguration > * scs) { + * const size_t STREAM_CONFIGURATION_SIZE = 5; + * const size_t STREAM_WIDTH_OFFSET = 0; + * const size_t STREAM_HEIGHT_OFFSET = 1; + * const size_t STREAM_FORMAT_OFFSET = 2; + * const size_t STREAM_IS_INPUT_OFFSET = 3; + * const size_t STREAM_USECASE_BITMAP_OFFSET = 4;

+ *
for (size_t i = 0; i < count; i+= STREAM_CONFIGURATION_SIZE) {
+     *     int32_t width = array[i + STREAM_WIDTH_OFFSET];
+     *     int32_t height = array[i + STREAM_HEIGHT_OFFSET];
+     *     int32_t format = array[i + STREAM_FORMAT_OFFSET];
+     *     int32_t isInput = array[i + STREAM_IS_INPUT_OFFSET];
+     *     int32_t supportedUsecases = array[i + STREAM_USECASE_BITMAP_OFFSET];
+     *     if (supportedUsecases & (1 << usecaseId)) {
+     *         StreamConfiguration sc = {format, width, height, isInput};
+     *         scs->add(sc);
+     *     }
+     * }
+     * 
+ *

}

+ * + * @see ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS + */ + ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS = + // int32[n*5] (acamera_metadata_enum_android_scaler_available_recommended_stream_configurations_t) + ACAMERA_SCALER_START + 14, + /** + *

Recommended mappings of image formats that are supported by this + * camera device for input streams, to their corresponding output formats.

+ * + *

Type: int32

+ * + *

This tag may appear in: + *

+ * + *

This is a recommended subset of the complete list of mappings found in + * android.scaler.availableInputOutputFormatsMap. The same requirements apply here as well. + * The list however doesn't need to contain all available and supported mappings. Instead of + * this developers must list only recommended and efficient entries. + * If set, the information will be available in the ZERO_SHUTTER_LAG recommended stream + * configuration see + * CameraCharacteristics#getRecommendedStreamConfigurationMap.

+ */ + ACAMERA_SCALER_AVAILABLE_RECOMMENDED_INPUT_OUTPUT_FORMATS_MAP = + // int32 + ACAMERA_SCALER_START + 15, ACAMERA_SCALER_END, /** @@ -5411,6 +5486,32 @@ typedef enum acamera_metadata_tag { */ ACAMERA_DEPTH_DEPTH_IS_EXCLUSIVE = // byte (acamera_metadata_enum_android_depth_depth_is_exclusive_t) ACAMERA_DEPTH_START + 4, + /** + *

Recommended depth stream configurations for common client use cases.

+ * + *

Type: int32[n*5]

+ * + *

This tag may appear in: + *

+ * + *

Optional subset of the ACAMERA_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS that + * contains similar tuples listed as + * (i.e. width, height, format, output/input stream, usecase bit field). + * Camera devices will be able to suggest particular depth stream configurations which are + * power and performance efficient for specific use cases. For more information about + * retrieving the suggestions see + * CameraCharacteristics#getRecommendedStreamConfigurationMap.

+ *

For data representation please refer to + * ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS

+ * + * @see ACAMERA_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS + * @see ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS + */ + ACAMERA_DEPTH_AVAILABLE_RECOMMENDED_DEPTH_STREAM_CONFIGURATIONS = + // int32[n*5] + ACAMERA_DEPTH_START + 5, ACAMERA_DEPTH_END, /** @@ -7300,6 +7401,67 @@ typedef enum acamera_metadata_enum_acamera_scaler_cropping_type { } acamera_metadata_enum_android_scaler_cropping_type_t; +// ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS +typedef enum acamera_metadata_enum_acamera_scaler_available_recommended_stream_configurations { + /** + *

Preview must only include non-stalling processed stream configurations with + * output formats like YUV_420_888, IMPLEMENTATION_DEFINED, etc.

+ */ + ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PREVIEW + = 0x0, + + /** + *

Video record must include stream configurations that match the advertised + * supported media profiles CamcorderProfile with + * IMPLEMENTATION_DEFINED format.

+ */ + ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RECORD + = 0x1, + + /** + *

Video snapshot must include stream configurations at least as big as + * the maximum RECORD resolutions and only with format BLOB + DATASPACE_JFIF + * format/dataspace combination (JPEG). Additionally the configurations shouldn't cause + * preview glitches and also be able to run at 30 fps.

+ */ + ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_VIDEO_SNAPSHOT + = 0x2, + + /** + *

Recommended snapshot stream configurations must include at least one with + * size close to ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE with BLOB + DATASPACE_JFIF + * format/dataspace combination (JPEG). Taking into account restrictions on aspect + * ratio, alignment etc. the area of the maximum suggested size shouldn’t be less than + * 97% of the sensor array size area.

+ * + * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE + */ + ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_SNAPSHOT + = 0x3, + + /** + *

If supported, recommended input stream configurations must only be advertised with + * ZSL along with other processed and/or stalling output formats.

+ */ + ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_ZSL = 0x4, + + /** + *

If supported, recommended raw stream configurations must only include RAW based + * output formats.

+ */ + ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RAW = 0x5, + + ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END + = 0x6, + + /** + *

Vendor defined use cases. These depend on the vendor implementation.

+ */ + ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_VENDOR_START + = 0x18, + +} acamera_metadata_enum_android_scaler_available_recommended_stream_configurations_t; + // ACAMERA_SENSOR_REFERENCE_ILLUMINANT1 typedef enum acamera_metadata_enum_acamera_sensor_reference_illuminant1 { diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp index 28d186abb4..8311a9bf5b 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.cpp +++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp @@ -69,7 +69,7 @@ status_t Parameters::initialize(CameraDeviceBase *device, int deviceVersion) { res = buildQuirks(); if (res != OK) return res; - const Size MAX_PREVIEW_SIZE = { MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT }; + Size maxPreviewSize = { MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT }; // Treat the H.264 max size as the max supported video size. MediaProfiles *videoEncoderProfiles = MediaProfiles::getInstance(); Vector encoders = videoEncoderProfiles->getVideoEncoders(); @@ -90,11 +90,16 @@ status_t Parameters::initialize(CameraDeviceBase *device, int deviceVersion) { } } // This is just an upper bound and may not be an actually valid video size - const Size VIDEO_SIZE_UPPER_BOUND = {maxVideoWidth, maxVideoHeight}; + Size videoSizeUpperBound = {maxVideoWidth, maxVideoHeight}; - res = getFilteredSizes(MAX_PREVIEW_SIZE, &availablePreviewSizes); + if (fastInfo.supportsPreferredConfigs) { + maxPreviewSize = getMaxSize(getPreferredPreviewSizes()); + videoSizeUpperBound = getMaxSize(getPreferredVideoSizes()); + } + + res = getFilteredSizes(maxPreviewSize, &availablePreviewSizes); if (res != OK) return res; - res = getFilteredSizes(VIDEO_SIZE_UPPER_BOUND, &availableVideoSizes); + res = getFilteredSizes(videoSizeUpperBound, &availableVideoSizes); if (res != OK) return res; // Select initial preview and video size that's under the initial bound and @@ -296,9 +301,13 @@ status_t Parameters::initialize(CameraDeviceBase *device, int deviceVersion) { Vector availableJpegSizes = getAvailableJpegSizes(); if (!availableJpegSizes.size()) return NO_INIT; - // TODO: Pick maximum pictureWidth = availableJpegSizes[0].width; pictureHeight = availableJpegSizes[0].height; + if (fastInfo.supportsPreferredConfigs) { + Size suggestedJpegSize = getMaxSize(getPreferredJpegSizes()); + pictureWidth = suggestedJpegSize.width; + pictureHeight = suggestedJpegSize.height; + } pictureWidthLastSet = pictureWidth; pictureHeightLastSet = pictureHeight; pictureSizeOverriden = false; @@ -1010,6 +1019,9 @@ status_t Parameters::buildFastInfo(CameraDeviceBase *device) { arrayHeight = activeArraySize.data.i32[3]; } else return NO_INIT; + fastInfo.supportsPreferredConfigs = + info->exists(ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS); + // We'll set the target FPS range for still captures to be as wide // as possible to give the HAL maximum latitude for exposure selection camera_metadata_ro_entry_t availableFpsRanges = @@ -1021,8 +1033,11 @@ status_t Parameters::buildFastInfo(CameraDeviceBase *device) { // Get supported preview fps ranges, up to default maximum. Vector supportedPreviewSizes; Vector supportedPreviewFpsRanges; - const Size PREVIEW_SIZE_BOUND = { MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT }; - status_t res = getFilteredSizes(PREVIEW_SIZE_BOUND, &supportedPreviewSizes); + Size previewSizeBound = { MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT }; + if (fastInfo.supportsPreferredConfigs) { + previewSizeBound = getMaxSize(getPreferredPreviewSizes()); + } + status_t res = getFilteredSizes(previewSizeBound, &supportedPreviewSizes); if (res != OK) return res; for (size_t i=0; i < availableFpsRanges.count; i += 2) { if (!isFpsSupported(supportedPreviewSizes, @@ -3106,6 +3121,67 @@ Vector Parameters::getAvailableJpegSizes() { return jpegSizes; } +Vector Parameters::getPreferredStreamConfigurations( + int32_t usecaseId) const { + const size_t STREAM_CONFIGURATION_SIZE = 5; + const size_t STREAM_WIDTH_OFFSET = 0; + const size_t STREAM_HEIGHT_OFFSET = 1; + const size_t STREAM_FORMAT_OFFSET = 2; + const size_t STREAM_IS_INPUT_OFFSET = 3; + const size_t STREAM_USECASE_BITMAP_OFFSET = 4; + Vector scs; + + if (fastInfo.supportsPreferredConfigs) { + camera_metadata_ro_entry_t availableStreamConfigs = staticInfo( + ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS); + for (size_t i = 0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) { + int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET]; + int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET]; + int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET]; + int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET]; + int32_t supportedUsecases = + availableStreamConfigs.data.i32[i + STREAM_USECASE_BITMAP_OFFSET]; + if (supportedUsecases & (1 << usecaseId)) { + StreamConfiguration sc = {format, width, height, isInput}; + scs.add(sc); + } + } + } + + return scs; +} + +Vector Parameters::getPreferredFilteredSizes(int32_t usecaseId, + int32_t format) const { + Vector sizes; + Vector scs = getPreferredStreamConfigurations(usecaseId); + for (const auto &it : scs) { + if (it.format == format) { + sizes.add({it.width, it.height}); + } + } + + return sizes; +} + +Vector Parameters::getPreferredJpegSizes() const { + return getPreferredFilteredSizes( + ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_SNAPSHOT, + HAL_PIXEL_FORMAT_BLOB); +} + +Vector Parameters::getPreferredPreviewSizes() const { + return getPreferredFilteredSizes( + ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PREVIEW, + HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED); +} + +Vector Parameters::getPreferredVideoSizes() const { + return getPreferredFilteredSizes( + ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RECORD, + HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED); +} + Parameters::CropRegion Parameters::calculateCropRegion(bool previewOnly) const { float zoomLeft, zoomTop, zoomWidth, zoomHeight; diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h index 42e7a47c82..9ef3f33d8f 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.h +++ b/services/camera/libcameraservice/api1/client2/Parameters.h @@ -247,6 +247,7 @@ struct Parameters { bool useFlexibleYuv; Size maxJpegSize; Size maxZslSize; + bool supportsPreferredConfigs; } fastInfo; // Quirks information; these are short-lived flags to enable workarounds for @@ -417,6 +418,9 @@ private: // returns an empty Vector if device HAL version does support it Vector getStreamConfigurations(); + // Helper function to extract the suggested stream configurations + Vector getPreferredStreamConfigurations(int32_t usecaseId) const; + // Helper function to get minimum frame duration for a jpeg size // return -1 if input jpeg size cannot be found in supported size list int64_t getJpegStreamMinFrameDurationNs(Parameters::Size size); @@ -438,6 +442,15 @@ private: // The maximum size is defined by comparing width first, when width ties comparing height. Size getMaxSize(const Vector& sizes); + // Helper function to filter and sort suggested sizes + Vector getPreferredFilteredSizes(int32_t usecaseId, int32_t format) const; + // Helper function to get the suggested jpeg sizes + Vector getPreferredJpegSizes() const; + // Helper function to get the suggested preview sizes + Vector getPreferredPreviewSizes() const; + // Helper function to get the suggested video sizes + Vector getPreferredVideoSizes() const; + int mDeviceVersion; uint8_t mDefaultSceneMode; };