Camera2: get stream configs by device verison
Starting from device version 3.2, the following tags:
ANDROID_SCALER_AVAILABLE_FORMATS
ANDROID_SCALER_AVAILABLE_JPEG_MIN_DURATIONS
ANDROID_SCALER_AVAILABLE_JPEG_SIZES
ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS
ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES
ANDROID_SCALER_AVAILABLE_RAW_MIN_DURATIONS
ANDROID_SCALER_AVAILABLE_RAW_SIZES
are deprecated and replaced by:
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS
Change-Id: Iadc34af0ea985a16a25759d7a9a3eb4845c486fd
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 0447979..a6f5a6c 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -53,12 +53,10 @@
int cameraFacing,
int clientPid,
uid_t clientUid,
- int servicePid,
- int deviceVersion):
+ int servicePid):
Camera2ClientBase(cameraService, cameraClient, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid),
- mParameters(cameraId, cameraFacing),
- mDeviceVersion(deviceVersion)
+ mParameters(cameraId, cameraFacing)
{
ATRACE_CALL();
@@ -80,7 +78,7 @@
{
SharedParameters::Lock l(mParameters);
- res = l.mParameters.initialize(&(mDevice->info()));
+ res = l.mParameters.initialize(&(mDevice->info()), mDeviceVersion);
if (res != OK) {
ALOGE("%s: Camera %d: unable to build defaults: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index fe0bf74..0e06195 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -89,8 +89,7 @@
int cameraFacing,
int clientPid,
uid_t clientUid,
- int servicePid,
- int deviceVersion);
+ int servicePid);
virtual ~Camera2Client();
@@ -170,7 +169,6 @@
void setPreviewCallbackFlagL(Parameters ¶ms, int flag);
status_t updateRequests(Parameters ¶ms);
- int mDeviceVersion;
// Used with stream IDs
static const int NO_STREAM = -1;
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 51b1980..6459300 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -29,6 +29,7 @@
#include "Parameters.h"
#include "system/camera.h"
+#include "hardware/camera_common.h"
#include <media/MediaProfiles.h>
#include <media/mediarecorder.h>
@@ -45,7 +46,7 @@
Parameters::~Parameters() {
}
-status_t Parameters::initialize(const CameraMetadata *info) {
+status_t Parameters::initialize(const CameraMetadata *info, int deviceVersion) {
status_t res;
if (info->entryCount() == 0) {
@@ -53,6 +54,7 @@
return BAD_VALUE;
}
Parameters::info = info;
+ mDeviceVersion = deviceVersion;
res = buildFastInfo();
if (res != OK) return res;
@@ -140,16 +142,14 @@
previewTransform = degToTransform(0,
cameraFacing == CAMERA_FACING_FRONT);
- camera_metadata_ro_entry_t availableFormats =
- staticInfo(ANDROID_SCALER_AVAILABLE_FORMATS);
-
{
String8 supportedPreviewFormats;
+ SortedVector<int32_t> outputFormats = getAvailableOutputFormats();
bool addComma = false;
- for (size_t i=0; i < availableFormats.count; i++) {
+ for (size_t i=0; i < outputFormats.size(); i++) {
if (addComma) supportedPreviewFormats += ",";
addComma = true;
- switch (availableFormats.data.i32[i]) {
+ switch (outputFormats[i]) {
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
supportedPreviewFormats +=
CameraParameters::PIXEL_FORMAT_YUV422SP;
@@ -191,7 +191,7 @@
default:
ALOGW("%s: Camera %d: Unknown preview format: %x",
- __FUNCTION__, cameraId, availableFormats.data.i32[i]);
+ __FUNCTION__, cameraId, outputFormats[i]);
addComma = false;
break;
}
@@ -239,24 +239,23 @@
supportedPreviewFrameRates);
}
- camera_metadata_ro_entry_t availableJpegSizes =
- staticInfo(ANDROID_SCALER_AVAILABLE_JPEG_SIZES, 2);
- if (!availableJpegSizes.count) return NO_INIT;
+ Vector<Size> availableJpegSizes = getAvailableJpegSizes();
+ if (!availableJpegSizes.size()) return NO_INIT;
// TODO: Pick maximum
- pictureWidth = availableJpegSizes.data.i32[0];
- pictureHeight = availableJpegSizes.data.i32[1];
+ pictureWidth = availableJpegSizes[0].width;
+ pictureHeight = availableJpegSizes[0].height;
params.setPictureSize(pictureWidth,
pictureHeight);
{
String8 supportedPictureSizes;
- for (size_t i=0; i < availableJpegSizes.count; i += 2) {
+ for (size_t i=0; i < availableJpegSizes.size(); i++) {
if (i != 0) supportedPictureSizes += ",";
supportedPictureSizes += String8::format("%dx%d",
- availableJpegSizes.data.i32[i],
- availableJpegSizes.data.i32[i+1]);
+ availableJpegSizes[i].width,
+ availableJpegSizes[i].height);
}
params.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
supportedPictureSizes);
@@ -952,9 +951,8 @@
staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS);
if (!availableFocalLengths.count) return NO_INIT;
- camera_metadata_ro_entry_t availableFormats =
- staticInfo(ANDROID_SCALER_AVAILABLE_FORMATS);
- if (!availableFormats.count) return NO_INIT;
+ SortedVector<int32_t> availableFormats = getAvailableOutputFormats();
+ if (!availableFormats.size()) return NO_INIT;
if (sceneModeOverrides.count > 0) {
@@ -1038,8 +1036,8 @@
// Check if the HAL supports HAL_PIXEL_FORMAT_YCbCr_420_888
fastInfo.useFlexibleYuv = false;
- for (size_t i = 0; i < availableFormats.count; i++) {
- if (availableFormats.data.i32[i] == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ for (size_t i = 0; i < availableFormats.size(); i++) {
+ if (availableFormats[i] == HAL_PIXEL_FORMAT_YCbCr_420_888) {
fastInfo.useFlexibleYuv = true;
break;
}
@@ -1198,8 +1196,7 @@
"is active!", __FUNCTION__);
return BAD_VALUE;
}
- camera_metadata_ro_entry_t availableFormats =
- staticInfo(ANDROID_SCALER_AVAILABLE_FORMATS);
+ SortedVector<int32_t> availableFormats = getAvailableOutputFormats();
// If using flexible YUV, always support NV21/YV12. Otherwise, check
// HAL's list.
if (! (fastInfo.useFlexibleYuv &&
@@ -1208,11 +1205,10 @@
validatedParams.previewFormat ==
HAL_PIXEL_FORMAT_YV12) ) ) {
// Not using flexible YUV format, so check explicitly
- for (i = 0; i < availableFormats.count; i++) {
- if (availableFormats.data.i32[i] ==
- validatedParams.previewFormat) break;
+ for (i = 0; i < availableFormats.size(); i++) {
+ if (availableFormats[i] == validatedParams.previewFormat) break;
}
- if (i == availableFormats.count) {
+ if (i == availableFormats.size()) {
ALOGE("%s: Requested preview format %s (0x%x) is not supported",
__FUNCTION__, newParams.getPreviewFormat(),
validatedParams.previewFormat);
@@ -1302,15 +1298,14 @@
&validatedParams.pictureHeight);
if (validatedParams.pictureWidth == pictureWidth ||
validatedParams.pictureHeight == pictureHeight) {
- camera_metadata_ro_entry_t availablePictureSizes =
- staticInfo(ANDROID_SCALER_AVAILABLE_JPEG_SIZES);
- for (i = 0; i < availablePictureSizes.count; i+=2) {
- if ((availablePictureSizes.data.i32[i] ==
+ Vector<Size> availablePictureSizes = getAvailableJpegSizes();
+ for (i = 0; i < availablePictureSizes.size(); i++) {
+ if ((availablePictureSizes[i].width ==
validatedParams.pictureWidth) &&
- (availablePictureSizes.data.i32[i+1] ==
+ (availablePictureSizes[i].height ==
validatedParams.pictureHeight)) break;
}
- if (i == availablePictureSizes.count) {
+ if (i == availablePictureSizes.size()) {
ALOGE("%s: Requested picture size %d x %d is not supported",
__FUNCTION__, validatedParams.pictureWidth,
validatedParams.pictureHeight);
@@ -2527,22 +2522,37 @@
ALOGE("%s: Input size is null", __FUNCTION__);
return BAD_VALUE;
}
+ sizes->clear();
- const size_t SIZE_COUNT = sizeof(Size) / sizeof(int);
- camera_metadata_ro_entry_t availableProcessedSizes =
- staticInfo(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, SIZE_COUNT);
- if (availableProcessedSizes.count < SIZE_COUNT) return BAD_VALUE;
-
- Size filteredSize;
- for (size_t i = 0; i < availableProcessedSizes.count; i += SIZE_COUNT) {
- filteredSize.width = availableProcessedSizes.data.i32[i];
- filteredSize.height = availableProcessedSizes.data.i32[i+1];
- // Need skip the preview sizes that are too large.
- if (filteredSize.width <= limit.width &&
- filteredSize.height <= limit.height) {
- sizes->push(filteredSize);
+ if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2) {
+ Vector<StreamConfiguration> scs = getStreamConfigurations();
+ for (size_t i=0; i < scs.size(); i++) {
+ const StreamConfiguration &sc = scs[i];
+ if (sc.isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+ sc.format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
+ sc.width <= limit.width && sc.height <= limit.height) {
+ Size sz = {sc.width, sc.height};
+ sizes->push(sz);
}
+ }
+ } else {
+ const size_t SIZE_COUNT = sizeof(Size) / sizeof(int);
+ camera_metadata_ro_entry_t availableProcessedSizes =
+ staticInfo(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, SIZE_COUNT);
+ if (availableProcessedSizes.count < SIZE_COUNT) return BAD_VALUE;
+
+ Size filteredSize;
+ for (size_t i = 0; i < availableProcessedSizes.count; i += SIZE_COUNT) {
+ filteredSize.width = availableProcessedSizes.data.i32[i];
+ filteredSize.height = availableProcessedSizes.data.i32[i+1];
+ // Need skip the preview sizes that are too large.
+ if (filteredSize.width <= limit.width &&
+ filteredSize.height <= limit.height) {
+ sizes->push(filteredSize);
+ }
+ }
}
+
if (sizes->isEmpty()) {
ALOGE("generated preview size list is empty!!");
return BAD_VALUE;
@@ -2576,6 +2586,78 @@
return maxSize;
}
+Vector<Parameters::StreamConfiguration> Parameters::getStreamConfigurations() {
+ const int STREAM_CONFIGURATION_SIZE = 4;
+ const int STREAM_FORMAT_OFFSET = 0;
+ const int STREAM_WIDTH_OFFSET = 1;
+ const int STREAM_HEIGHT_OFFSET = 2;
+ const int STREAM_IS_INPUT_OFFSET = 3;
+ Vector<StreamConfiguration> scs;
+ if (mDeviceVersion < CAMERA_DEVICE_API_VERSION_3_2) {
+ ALOGE("StreamConfiguration is only valid after device HAL 3.2!");
+ return scs;
+ }
+
+ camera_metadata_ro_entry_t availableStreamConfigs =
+ staticInfo(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
+ for (size_t i=0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
+ int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
+ int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
+ int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
+ int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
+ StreamConfiguration sc = {format, width, height, isInput};
+ scs.add(sc);
+ }
+ return scs;
+}
+
+SortedVector<int32_t> Parameters::getAvailableOutputFormats() {
+ SortedVector<int32_t> outputFormats; // Non-duplicated output formats
+ if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2) {
+ Vector<StreamConfiguration> scs = getStreamConfigurations();
+ for (size_t i=0; i < scs.size(); i++) {
+ const StreamConfiguration &sc = scs[i];
+ if (sc.isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) {
+ outputFormats.add(sc.format);
+ }
+ }
+ } else {
+ camera_metadata_ro_entry_t availableFormats = staticInfo(ANDROID_SCALER_AVAILABLE_FORMATS);
+ for (size_t i=0; i < availableFormats.count; i++) {
+ outputFormats.add(availableFormats.data.i32[i]);
+ }
+ }
+ return outputFormats;
+}
+
+Vector<Parameters::Size> Parameters::getAvailableJpegSizes() {
+ Vector<Parameters::Size> jpegSizes;
+ if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2) {
+ Vector<StreamConfiguration> scs = getStreamConfigurations();
+ for (size_t i=0; i < scs.size(); i++) {
+ const StreamConfiguration &sc = scs[i];
+ if (sc.isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+ sc.format == HAL_PIXEL_FORMAT_BLOB) {
+ Size sz = {sc.width, sc.height};
+ jpegSizes.add(sz);
+ }
+ }
+ } else {
+ const int JPEG_SIZE_ENTRY_COUNT = 2;
+ const int WIDTH_OFFSET = 0;
+ const int HEIGHT_OFFSET = 1;
+ camera_metadata_ro_entry_t availableJpegSizes =
+ staticInfo(ANDROID_SCALER_AVAILABLE_JPEG_SIZES);
+ for (size_t i=0; i < availableJpegSizes.count; i+= JPEG_SIZE_ENTRY_COUNT) {
+ int width = availableJpegSizes.data.i32[i + WIDTH_OFFSET];
+ int height = availableJpegSizes.data.i32[i + HEIGHT_OFFSET];
+ Size sz = {width, height};
+ jpegSizes.add(sz);
+ }
+ }
+ return jpegSizes;
+}
+
Parameters::CropRegion Parameters::calculateCropRegion(
Parameters::CropRegion::Outputs outputs) const {
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h
index 28dd788..f95c69a 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.h
+++ b/services/camera/libcameraservice/api1/client2/Parameters.h
@@ -226,7 +226,7 @@
~Parameters();
// Sets up default parameters
- status_t initialize(const CameraMetadata *info);
+ status_t initialize(const CameraMetadata *info, int deviceVersion);
// Build fast-access device static info from static info
status_t buildFastInfo();
@@ -346,6 +346,24 @@
status_t getFilteredSizes(Size limit, Vector<Size> *sizes);
// Get max size (from the size array) that matches the given aspect ratio.
Size getMaxSizeForRatio(float ratio, const int32_t* sizeArray, size_t count);
+
+ struct StreamConfiguration {
+ int32_t format;
+ int32_t width;
+ int32_t height;
+ int32_t isInput;
+ };
+ // Helper function extract available stream configuration
+ // Only valid since device HAL version 3.2
+ // returns an empty Vector if device HAL version does support it
+ Vector<StreamConfiguration> getStreamConfigurations();
+
+ // Helper function to get non-duplicated available output formats
+ SortedVector<int32_t> getAvailableOutputFormats();
+ // Helper function to get available output jpeg sizes
+ Vector<Size> getAvailableJpegSizes();
+
+ int mDeviceVersion;
};
// This class encapsulates the Parameters class so that it can only be accessed