diff options
author | Eino-Ville Talvala <etalvala@google.com> | 2015-04-29 17:36:58 -0700 |
---|---|---|
committer | Eino-Ville Talvala <etalvala@google.com> | 2015-04-30 15:52:21 -0700 |
commit | d48521fc2f7c34623a745728a07dad728da49254 (patch) | |
tree | 6a13d3322a6ecf2583b1227932f11220983216c5 | |
parent | f62a067a5b21c840c915d36392679346ac0abfd7 (diff) | |
download | frameworks_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.cpp | 117 | ||||
-rw-r--r-- | services/camera/libcameraservice/api1/client2/Parameters.h | 13 |
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; |