Camera: Use recommended configs for shim supported parameters

The legacy camera shim layer currently uses various heuristics
in order to determine valid supported preview/video/snapshot
sizes and formats. This makes the code complex and in some
cases the result is not optimal in terms of power and
performance. If the camera supports recommended stream
configurations, then use the suggested stream
configurations to generate the above supported lists.

Bug: 64029608
Test: Camera CTS
Change-Id: I6ed1d50b3d1a854421f3d119be2e32211e8a4c35
gugelfrei
Emilian Peev 6 years ago
parent 49fb89d3a0
commit 0505d7c2c4

@ -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,
/**
* <p>Recommended stream configurations for common client use cases.</p>
*
* <p>Type: int32[n*5] (acamera_metadata_enum_android_scaler_available_recommended_stream_configurations_t)</p>
*
* <p>This tag may appear in:
* <ul>
* <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
* </ul></p>
*
* <p>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
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#getRecommendedStreamConfigurationMap">CameraCharacteristics#getRecommendedStreamConfigurationMap</a>.</p>
* <p>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:</p>
* <p>struct StreamConfiguration {
* int32_t format;
* int32_t width;
* int32_t height;
* int32_t isInput; };</p>
* <p>void getPreferredStreamConfigurations(
* int32_t *array, size_t count, int32_t usecaseId,
* Vector &lt; StreamConfiguration &gt; * 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;</p>
* <pre><code>for (size_t i = 0; i &lt; 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 &amp; (1 &lt;&lt; usecaseId)) {
* StreamConfiguration sc = {format, width, height, isInput};
* scs-&gt;add(sc);
* }
* }
* </code></pre>
* <p>}</p>
*
* @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,
/**
* <p>Recommended mappings of image formats that are supported by this
* camera device for input streams, to their corresponding output formats.</p>
*
* <p>Type: int32</p>
*
* <p>This tag may appear in:
* <ul>
* <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
* </ul></p>
*
* <p>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
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#getRecommendedStreamConfigurationMap">CameraCharacteristics#getRecommendedStreamConfigurationMap</a>.</p>
*/
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,
/**
* <p>Recommended depth stream configurations for common client use cases.</p>
*
* <p>Type: int32[n*5]</p>
*
* <p>This tag may appear in:
* <ul>
* <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
* </ul></p>
*
* <p>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
* <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#getRecommendedStreamConfigurationMap">CameraCharacteristics#getRecommendedStreamConfigurationMap</a>.</p>
* <p>For data representation please refer to
* ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS</p>
*
* @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 {
/**
* <p>Preview must only include non-stalling processed stream configurations with
* output formats like YUV_420_888, IMPLEMENTATION_DEFINED, etc.</p>
*/
ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PREVIEW
= 0x0,
/**
* <p>Video record must include stream configurations that match the advertised
* supported media profiles <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a> with
* IMPLEMENTATION_DEFINED format.</p>
*/
ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RECORD
= 0x1,
/**
* <p>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.</p>
*/
ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_VIDEO_SNAPSHOT
= 0x2,
/**
* <p>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 shouldnt be less than
* 97% of the sensor array size area.</p>
*
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
*/
ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_SNAPSHOT
= 0x3,
/**
* <p>If supported, recommended input stream configurations must only be advertised with
* ZSL along with other processed and/or stalling output formats.</p>
*/
ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_ZSL = 0x4,
/**
* <p>If supported, recommended raw stream configurations must only include RAW based
* output formats.</p>
*/
ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_RAW = 0x5,
ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END
= 0x6,
/**
* <p>Vendor defined use cases. These depend on the vendor implementation.</p>
*/
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 {

@ -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<video_encoder> 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<Size> 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<Size> supportedPreviewSizes;
Vector<FpsRange> 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::Size> Parameters::getAvailableJpegSizes() {
return jpegSizes;
}
Vector<Parameters::StreamConfiguration> 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<StreamConfiguration> 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::Size> Parameters::getPreferredFilteredSizes(int32_t usecaseId,
int32_t format) const {
Vector<Parameters::Size> sizes;
Vector<StreamConfiguration> scs = getPreferredStreamConfigurations(usecaseId);
for (const auto &it : scs) {
if (it.format == format) {
sizes.add({it.width, it.height});
}
}
return sizes;
}
Vector<Parameters::Size> Parameters::getPreferredJpegSizes() const {
return getPreferredFilteredSizes(
ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_SNAPSHOT,
HAL_PIXEL_FORMAT_BLOB);
}
Vector<Parameters::Size> Parameters::getPreferredPreviewSizes() const {
return getPreferredFilteredSizes(
ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PREVIEW,
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
}
Vector<Parameters::Size> 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;

@ -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<StreamConfiguration> getStreamConfigurations();
// Helper function to extract the suggested stream configurations
Vector<StreamConfiguration> 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<Size>& sizes);
// Helper function to filter and sort suggested sizes
Vector<Parameters::Size> getPreferredFilteredSizes(int32_t usecaseId, int32_t format) const;
// Helper function to get the suggested jpeg sizes
Vector<Size> getPreferredJpegSizes() const;
// Helper function to get the suggested preview sizes
Vector<Size> getPreferredPreviewSizes() const;
// Helper function to get the suggested video sizes
Vector<Size> getPreferredVideoSizes() const;
int mDeviceVersion;
uint8_t mDefaultSceneMode;
};

Loading…
Cancel
Save