summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEino-Ville Talvala <etalvala@google.com>2015-04-29 17:36:58 -0700
committerEino-Ville Talvala <etalvala@google.com>2015-04-30 15:52:21 -0700
commitd48521fc2f7c34623a745728a07dad728da49254 (patch)
tree6a13d3322a6ecf2583b1227932f11220983216c5
parentf62a067a5b21c840c915d36392679346ac0abfd7 (diff)
downloadframeworks_av-d48521fc2f7c34623a745728a07dad728da49254.zip
frameworks_av-d48521fc2f7c34623a745728a07dad728da49254.tar.gz
frameworks_av-d48521fc2f7c34623a745728a07dad728da49254.tar.bz2
Camera: API1 shim: Don't tightly apply crop region
Due to older HAL compatibility, we have been setting a tight crop region that just bounds the current output streams. However, this did not take into account any possible ZSL output stream, so correct application of our stream cropping rules to ZSL results in double-crop scenarios, if the ZSL stream aspect ratio does not match the aspect ratio of the other output streams. Since all current HALs follow the correct stream cropping rules (or at least sufficiently ignore them for ZSL), simplify the cropping substantially - now either calculate the crop region based purely off the active array dimensions and zoom factor, or purely off the preview stream and zoom factor. The former is used for setting the request crop, and the latter is used for converting coordinates for metering regions. Bug: 20316691 Change-Id: I5a0bc2e7c09cf60fbae4220566540ca9e674d652
-rw-r--r--services/camera/libcameraservice/api1/client2/Parameters.cpp117
-rw-r--r--services/camera/libcameraservice/api1/client2/Parameters.h13
2 files changed, 37 insertions, 93 deletions
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 6b0f8b5..c3a6842 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -2100,12 +2100,7 @@ status_t Parameters::updateRequest(CameraMetadata *request) const {
delete[] reqMeteringAreas;
- /* don't include jpeg thumbnail size - it's valid for
- it to be set to (0,0), meaning 'no thumbnail' */
- CropRegion crop = calculateCropRegion( (CropRegion::Outputs)(
- CropRegion::OUTPUT_PREVIEW |
- CropRegion::OUTPUT_VIDEO |
- CropRegion::OUTPUT_PICTURE ));
+ CropRegion crop = calculateCropRegion(/*previewOnly*/ false);
int32_t reqCropRegion[4] = {
static_cast<int32_t>(crop.left),
static_cast<int32_t>(crop.top),
@@ -2603,7 +2598,7 @@ int Parameters::cropXToArray(int x) const {
ALOG_ASSERT(x >= 0, "Crop-relative X coordinate = '%d' is out of bounds"
"(lower = 0)", x);
- CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
+ CropRegion previewCrop = calculateCropRegion(/*previewOnly*/ true);
ALOG_ASSERT(x < previewCrop.width, "Crop-relative X coordinate = '%d' "
"is out of bounds (upper = %f)", x, previewCrop.width);
@@ -2619,7 +2614,7 @@ int Parameters::cropYToArray(int y) const {
ALOG_ASSERT(y >= 0, "Crop-relative Y coordinate = '%d' is out of bounds "
"(lower = 0)", y);
- CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
+ CropRegion previewCrop = calculateCropRegion(/*previewOnly*/ true);
ALOG_ASSERT(y < previewCrop.height, "Crop-relative Y coordinate = '%d' is "
"out of bounds (upper = %f)", y, previewCrop.height);
@@ -2634,12 +2629,12 @@ int Parameters::cropYToArray(int y) const {
}
int Parameters::normalizedXToCrop(int x) const {
- CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
+ CropRegion previewCrop = calculateCropRegion(/*previewOnly*/ true);
return (x + 1000) * (previewCrop.width - 1) / 2000;
}
int Parameters::normalizedYToCrop(int y) const {
- CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
+ CropRegion previewCrop = calculateCropRegion(/*previewOnly*/ true);
return (y + 1000) * (previewCrop.height - 1) / 2000;
}
@@ -2855,8 +2850,7 @@ Vector<Parameters::Size> Parameters::getAvailableJpegSizes() {
return jpegSizes;
}
-Parameters::CropRegion Parameters::calculateCropRegion(
- Parameters::CropRegion::Outputs outputs) const {
+Parameters::CropRegion Parameters::calculateCropRegion(bool previewOnly) const {
float zoomLeft, zoomTop, zoomWidth, zoomHeight;
@@ -2880,90 +2874,45 @@ Parameters::CropRegion Parameters::calculateCropRegion(
maxDigitalZoom.data.f[0], zoomIncrement, zoomRatio, previewWidth,
previewHeight, fastInfo.arrayWidth, fastInfo.arrayHeight);
- /*
- * Assumption: On the HAL side each stream buffer calculates its crop
- * rectangle as follows:
- * cropRect = (zoomLeft, zoomRight,
- * zoomWidth, zoomHeight * zoomWidth / outputWidth);
- *
- * Note that if zoomWidth > bufferWidth, the new cropHeight > zoomHeight
- * (we can then get into trouble if the cropHeight > arrayHeight).
- * By selecting the zoomRatio based on the smallest outputRatio, we
- * guarantee this will never happen.
- */
+ if (previewOnly) {
+ // Calculate a tight crop region for the preview stream only
+ float previewRatio = static_cast<float>(previewWidth) / previewHeight;
- // Enumerate all possible output sizes, select the one with the smallest
- // aspect ratio
- float minOutputWidth, minOutputHeight, minOutputRatio;
- {
- float outputSizes[][2] = {
- { static_cast<float>(previewWidth),
- static_cast<float>(previewHeight) },
- { static_cast<float>(videoWidth),
- static_cast<float>(videoHeight) },
- { static_cast<float>(jpegThumbSize[0]),
- static_cast<float>(jpegThumbSize[1]) },
- { static_cast<float>(pictureWidth),
- static_cast<float>(pictureHeight) },
- };
-
- minOutputWidth = outputSizes[0][0];
- minOutputHeight = outputSizes[0][1];
- minOutputRatio = minOutputWidth / minOutputHeight;
- for (unsigned int i = 0;
- i < sizeof(outputSizes) / sizeof(outputSizes[0]);
- ++i) {
-
- // skip over outputs we don't want to consider for the crop region
- if ( !((1 << i) & outputs) ) {
- continue;
- }
-
- float outputWidth = outputSizes[i][0];
- float outputHeight = outputSizes[i][1];
- float outputRatio = outputWidth / outputHeight;
-
- if (minOutputRatio > outputRatio) {
- minOutputRatio = outputRatio;
- minOutputWidth = outputWidth;
- minOutputHeight = outputHeight;
- }
+ /* Ensure that the width/height never go out of bounds
+ * by scaling across a diffent dimension if an out-of-bounds
+ * possibility exists.
+ *
+ * e.g. if the previewratio < arrayratio and e.g. zoomratio = 1.0, then by
+ * calculating the zoomWidth from zoomHeight we'll actually get a
+ * zoomheight > arrayheight
+ */
+ float arrayRatio = 1.f * fastInfo.arrayWidth / fastInfo.arrayHeight;
+ if (previewRatio >= arrayRatio) {
+ // Adjust the height based on the width
+ zoomWidth = fastInfo.arrayWidth / zoomRatio;
+ zoomHeight = zoomWidth *
+ previewHeight / previewWidth;
- // and then use this output ratio instead of preview output ratio
- ALOGV("Enumerating output ratio %f = %f / %f, min is %f",
- outputRatio, outputWidth, outputHeight, minOutputRatio);
+ } else {
+ // Adjust the width based on the height
+ zoomHeight = fastInfo.arrayHeight / zoomRatio;
+ zoomWidth = zoomHeight *
+ previewWidth / previewHeight;
}
- }
-
- /* Ensure that the width/height never go out of bounds
- * by scaling across a diffent dimension if an out-of-bounds
- * possibility exists.
- *
- * e.g. if the previewratio < arrayratio and e.g. zoomratio = 1.0, then by
- * calculating the zoomWidth from zoomHeight we'll actually get a
- * zoomheight > arrayheight
- */
- float arrayRatio = 1.f * fastInfo.arrayWidth / fastInfo.arrayHeight;
- if (minOutputRatio >= arrayRatio) {
- // Adjust the height based on the width
- zoomWidth = fastInfo.arrayWidth / zoomRatio;
- zoomHeight = zoomWidth *
- minOutputHeight / minOutputWidth;
-
} else {
- // Adjust the width based on the height
+ // Calculate the global crop region with a shape matching the active
+ // array.
+ zoomWidth = fastInfo.arrayWidth / zoomRatio;
zoomHeight = fastInfo.arrayHeight / zoomRatio;
- zoomWidth = zoomHeight *
- minOutputWidth / minOutputHeight;
}
- // centering the zoom area within the active area
+
+ // center the zoom area within the active area
zoomLeft = (fastInfo.arrayWidth - zoomWidth) / 2;
zoomTop = (fastInfo.arrayHeight - zoomHeight) / 2;
ALOGV("Crop region calculated (x=%d,y=%d,w=%f,h=%f) for zoom=%d",
(int32_t)zoomLeft, (int32_t)zoomTop, zoomWidth, zoomHeight, this->zoom);
-
CropRegion crop = { zoomLeft, zoomTop, zoomWidth, zoomHeight };
return crop;
}
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h
index e628a7e..46d48bc 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.h
+++ b/services/camera/libcameraservice/api1/client2/Parameters.h
@@ -271,21 +271,16 @@ struct Parameters {
// if video snapshot size is currently overridden
bool isJpegSizeOverridden();
- // Calculate the crop region rectangle based on current stream sizes
+ // Calculate the crop region rectangle, either tightly about the preview
+ // resolution, or a region just based on the active array; both take
+ // into account the current zoom level.
struct CropRegion {
float left;
float top;
float width;
float height;
-
- enum Outputs {
- OUTPUT_PREVIEW = 0x01,
- OUTPUT_VIDEO = 0x02,
- OUTPUT_JPEG_THUMBNAIL = 0x04,
- OUTPUT_PICTURE = 0x08,
- };
};
- CropRegion calculateCropRegion(CropRegion::Outputs outputs) const;
+ CropRegion calculateCropRegion(bool previewOnly) const;
// Calculate the field of view of the high-resolution JPEG capture
status_t calculatePictureFovs(float *horizFov, float *vertFov) const;