Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a6e4532 authored by Igor Murashkin's avatar Igor Murashkin
Browse files

Camera2: Fix metering regions to take into account the current zoom/crop region

Also adds a quirk to disable this fix to work around for incompliant HALs

Bug: 7246065
Change-Id: I80bad25e56ba59149270238e5639bb33cae495ae
parent 63dc1992
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -334,6 +334,10 @@ status_t Camera2Client::dump(int fd, const Vector<String16>& args) {
        result.appendFormat("    useZslFormat\n");
        haveQuirk = true;
    }
    if (p.quirks.meteringCropRegion) {
        result.appendFormat("    meteringCropRegion\n");
        haveQuirk = true;
    }
    if (!haveQuirk) {
        result.appendFormat("    none\n");
    }
+122 −9
Original line number Diff line number Diff line
@@ -929,6 +929,11 @@ status_t Parameters::buildQuirks() {
    ALOGV_IF(quirks.useZslFormat, "Camera %d: Quirk useZslFormat enabled",
            cameraId);

    entry = info->find(ANDROID_QUIRKS_METERING_CROP_REGION);
    quirks.meteringCropRegion = (entry.count != 0 && entry.data.u8[0] == 1);
    ALOGV_IF(quirks.meteringCropRegion, "Camera %d: Quirk meteringCropRegion"
                " enabled", cameraId);

    return OK;
}

@@ -1726,7 +1731,12 @@ status_t Parameters::updateRequest(CameraMetadata *request) const {
    if (res != OK) return res;
    delete[] reqMeteringAreas;

    CropRegion crop = calculateCropRegion();
    /* 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    ));
    int32_t reqCropRegion[3] = { crop.left, crop.top, crop.width };
    res = request->update(ANDROID_SCALER_CROP_REGION,
            reqCropRegion, 3);
@@ -2161,23 +2171,123 @@ int Parameters::degToTransform(int degrees, bool mirror) {
    return -1;
}

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);
    ALOG_ASSERT(x < previewCrop.width, "Crop-relative X coordinate = '%d' "
                    "is out of bounds (upper = %d)", x, previewCrop.width);

    int ret = x + previewCrop.left;

    ALOG_ASSERT( (ret >= 0 && ret < fastInfo.arrayWidth),
        "Calculated pixel array value X = '%d' is out of bounds (upper = %d)",
        ret, fastInfo.arrayWidth);
    return ret;
}

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);
    ALOG_ASSERT(y < previewCrop.height, "Crop-relative Y coordinate = '%d' is "
                "out of bounds (upper = %d)", y, previewCrop.height);

    int ret = y + previewCrop.top;

    ALOG_ASSERT( (ret >= 0 && ret < fastInfo.arrayHeight),
        "Calculated pixel array value Y = '%d' is out of bounds (upper = %d)",
        ret, fastInfo.arrayHeight);

    return ret;

}

int Parameters::normalizedXToCrop(int x) const {
    CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
    return (x + 1000) * (previewCrop.width - 1) / 2000;
}

int Parameters::normalizedYToCrop(int y) const {
    CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
    return (y + 1000) * (previewCrop.height - 1) / 2000;
}

int Parameters::arrayXToCrop(int x) const {
    CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
    return x - previewCrop.left;
}

int Parameters::arrayYToCrop(int y) const {
    CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
    return y - previewCrop.top;
}

int Parameters::cropXToNormalized(int x) const {
    CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
    return x * 2000 / (previewCrop.width - 1) - 1000;
}

int Parameters::cropYToNormalized(int y) const {
    CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
    return y * 2000 / (previewCrop.height - 1) - 1000;
}

int Parameters::arrayXToNormalized(int width) const {
    int ret = cropXToNormalized(arrayXToCrop(width));

    ALOG_ASSERT(ret >= -1000, "Calculated normalized value out of "
        "lower bounds %d", ret);
    ALOG_ASSERT(ret <= 1000, "Calculated normalized value out of "
        "upper bounds %d", ret);

    // Work-around for HAL pre-scaling the coordinates themselves
    if (quirks.meteringCropRegion) {
        return width * 2000 / (fastInfo.arrayWidth - 1) - 1000;
    }

    return ret;
}

int Parameters::arrayYToNormalized(int height) const {
    int ret = cropYToNormalized(arrayYToCrop(height));

    ALOG_ASSERT(ret >= -1000, "Calculated normalized value out of lower bounds"
        " %d", ret);
    ALOG_ASSERT(ret <= 1000, "Calculated normalized value out of upper bounds"
        " %d", ret);

    // Work-around for HAL pre-scaling the coordinates themselves
    if (quirks.meteringCropRegion) {
        return height * 2000 / (fastInfo.arrayHeight - 1) - 1000;
    }

    return ret;
}

int Parameters::normalizedXToArray(int x) const {

    // Work-around for HAL pre-scaling the coordinates themselves
    if (quirks.meteringCropRegion) {
        return (x + 1000) * (fastInfo.arrayWidth - 1) / 2000;
    }

    return cropXToArray(normalizedXToCrop(x));
}

int Parameters::normalizedYToArray(int y) const {
    // Work-around for HAL pre-scaling the coordinates themselves
    if (quirks.meteringCropRegion) {
        return (y + 1000) * (fastInfo.arrayHeight - 1) / 2000;
    }

Parameters::CropRegion Parameters::calculateCropRegion(void) const {
    return cropYToArray(normalizedYToCrop(y));
}

Parameters::CropRegion Parameters::calculateCropRegion(
                            Parameters::CropRegion::Outputs outputs) const {

    float zoomLeft, zoomTop, zoomWidth, zoomHeight;

@@ -2220,9 +2330,7 @@ Parameters::CropRegion Parameters::calculateCropRegion(void) const {
        float outputSizes[][2] = {
            { previewWidth,     previewHeight },
            { videoWidth,       videoHeight },
            /* don't include jpeg thumbnail size - it's valid for
               it to be set to (0,0), meaning 'no thumbnail' */
        //  { jpegThumbSize[0], jpegThumbSize[1] },
            { jpegThumbSize[0], jpegThumbSize[1] },
            { pictureWidth,     pictureHeight },
        };

@@ -2233,6 +2341,11 @@ Parameters::CropRegion Parameters::calculateCropRegion(void) const {
             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;
+24 −1
Original line number Diff line number Diff line
@@ -186,6 +186,7 @@ struct Parameters {
    struct Quirks {
        bool triggerAfWithAuto;
        bool useZslFormat;
        bool meteringCropRegion;
    } quirks;

    /**
@@ -228,8 +229,15 @@ struct Parameters {
        float top;
        float width;
        float height;

        enum Outputs {
            OUTPUT_PREVIEW         = 0x01,
            OUTPUT_VIDEO           = 0x02,
            OUTPUT_JPEG_THUMBNAIL  = 0x04,
            OUTPUT_PICTURE         = 0x08,
        };
    };
    CropRegion calculateCropRegion(void) const;
    CropRegion calculateCropRegion(CropRegion::Outputs outputs) const;

    // Static methods for debugging and converting between camera1 and camera2
    // parameters
@@ -275,6 +283,21 @@ struct Parameters {

    int32_t fpsFromRange(int32_t min, int32_t max) const;

private:

    // Convert between HAL2 sensor array coordinates and
    // viewfinder crop-region relative array coordinates
    int cropXToArray(int x) const;
    int cropYToArray(int y) const;
    int arrayXToCrop(int x) const;
    int arrayYToCrop(int y) const;

    // Convert between viewfinder crop-region relative array coordinates
    // and camera API (-1000,1000)-(1000,1000) normalized coords
    int cropXToNormalized(int x) const;
    int cropYToNormalized(int y) const;
    int normalizedXToCrop(int x) const;
    int normalizedYToCrop(int y) const;
};

// This class encapsulates the Parameters class so that it can only be accessed