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

Commit 0f9c1a8a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Camera: Make sure metering regions are valid in capture result"

parents cc0c34ac cd8811c1
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -128,12 +128,41 @@ status_t fixupMonochromeTags(
    return res;
}

void correctMeteringRegions(camera_metadata_t *meta) {
    if (meta == nullptr) return;

    uint32_t meteringRegionKeys[] = {
            ANDROID_CONTROL_AE_REGIONS,
            ANDROID_CONTROL_AWB_REGIONS,
            ANDROID_CONTROL_AF_REGIONS };

    for (uint32_t key : meteringRegionKeys) {
        camera_metadata_entry_t entry;
        int res = find_camera_metadata_entry(meta, key, &entry);
        if (res != OK) continue;

        for (size_t i = 0; i < entry.count; i += 5) {
            if (entry.data.i32[0] > entry.data.i32[2]) {
                ALOGW("%s: Invalid metering region (%d): left: %d, right: %d",
                        __FUNCTION__, key, entry.data.i32[0], entry.data.i32[2]);
                entry.data.i32[2] = entry.data.i32[0];
            }
            if (entry.data.i32[1] > entry.data.i32[3]) {
                ALOGW("%s: Invalid metering region (%d): top: %d, bottom: %d",
                        __FUNCTION__, key, entry.data.i32[1], entry.data.i32[3]);
                entry.data.i32[3] = entry.data.i32[1];
            }
        }
    }
}

void insertResultLocked(CaptureOutputStates& states, CaptureResult *result, uint32_t frameNumber) {
    if (result == nullptr) return;

    camera_metadata_t *meta = const_cast<camera_metadata_t *>(
            result->mMetadata.getAndLock());
    set_camera_metadata_vendor_id(meta, states.vendorTagId);
    correctMeteringRegions(meta);
    result->mMetadata.unlock(meta);

    if (result->mMetadata.update(ANDROID_REQUEST_FRAME_COUNT,
@@ -152,6 +181,7 @@ void insertResultLocked(CaptureOutputStates& states, CaptureResult *result, uint
        camera_metadata_t *pmeta = const_cast<camera_metadata_t *>(
                physicalMetadata.mPhysicalCameraMetadata.getAndLock());
        set_camera_metadata_vendor_id(pmeta, states.vendorTagId);
        correctMeteringRegions(pmeta);
        physicalMetadata.mPhysicalCameraMetadata.unlock(pmeta);
    }

+20 −20
Original line number Diff line number Diff line
@@ -354,17 +354,8 @@ status_t ZoomRatioMapper::separateZoomFromCropLocked(CameraMetadata* metadata, b
            if (weight == 0) {
                continue;
            }
            // Top left (inclusive)
            scaleCoordinates(entry.data.i32 + j, 1, zoomRatio, true /*clamp*/, arrayWidth,
            scaleRegion(entry.data.i32 + j, zoomRatio, arrayWidth,
                    arrayHeight);
            // Bottom right (exclusive): Use adjacent inclusive pixel to
            // calculate.
            entry.data.i32[j+2] -= 1;
            entry.data.i32[j+3] -= 1;
            scaleCoordinates(entry.data.i32 + j + 2, 1, zoomRatio, true /*clamp*/, arrayWidth,
                    arrayHeight);
            entry.data.i32[j+2] += 1;
            entry.data.i32[j+3] += 1;
        }
    }

@@ -401,17 +392,8 @@ status_t ZoomRatioMapper::combineZoomAndCropLocked(CameraMetadata* metadata, boo
            if (weight == 0) {
                continue;
            }
            // Top-left (inclusive)
            scaleCoordinates(entry.data.i32 + j, 1, 1.0 / zoomRatio, true /*clamp*/, arrayWidth,
            scaleRegion(entry.data.i32 + j, 1.0 / zoomRatio, arrayWidth,
                    arrayHeight);
            // Bottom-right (exclusive): Use adjacent inclusive pixel to
            // calculate.
            entry.data.i32[j+2] -= 1;
            entry.data.i32[j+3] -= 1;
            scaleCoordinates(entry.data.i32 + j + 2, 1, 1.0 / zoomRatio, true /*clamp*/, arrayWidth,
                    arrayHeight);
            entry.data.i32[j+2] += 1;
            entry.data.i32[j+3] += 1;
        }
    }
    for (auto rect : kRectsToCorrect) {
@@ -470,6 +452,24 @@ void ZoomRatioMapper::scaleCoordinates(int32_t* coordPairs, int coordCount,
    }
}

void ZoomRatioMapper::scaleRegion(int32_t* region, float scaleRatio,
        int32_t arrayWidth, int32_t arrayHeight) {
    // Top-left (inclusive)
    scaleCoordinates(region, 1, scaleRatio, true /*clamp*/, arrayWidth,
            arrayHeight);
    // Bottom-right (exclusive): Use adjacent inclusive pixel to
    // calculate.
    region[2] -= 1;
    region[3] -= 1;
    scaleCoordinates(region + 2, 1, scaleRatio, true /*clamp*/, arrayWidth,
            arrayHeight);
    region[2] += 1;
    region[3] += 1;
    // Make sure bottom-right >= top-left
    region[2] = std::max(region[0], region[2]);
    region[3] = std::max(region[1], region[3]);
}

void ZoomRatioMapper::scaleRects(int32_t* rects, int rectCount,
        float scaleRatio, int32_t arrayWidth, int32_t arrayHeight) {
    for (int i = 0; i < rectCount * 4; i += 4) {
+2 −0
Original line number Diff line number Diff line
@@ -69,6 +69,8 @@ class ZoomRatioMapper : public CoordinateMapper {
  public: // Visible for testing. Do not use concurently.
    void scaleCoordinates(int32_t* coordPairs, int coordCount,
            float scaleRatio, bool clamp, int32_t arrayWidth, int32_t arrayHeight);
    void scaleRegion(int32_t* region, float scaleRatio,
            int32_t arrayWidth, int32_t arrayHeight);

    bool isValid() { return mIsValid; }
  private:
+13 −2
Original line number Diff line number Diff line
@@ -160,11 +160,9 @@ void subScaleCoordinatesTest(bool usePreCorrectArray) {
            false/*hasZoomRatioRange*/, zoomRatioRange,
            usePreCorrectArray));

    size_t index = 0;
    int32_t width = testActiveArraySize[2];
    int32_t height = testActiveArraySize[3];
    if (usePreCorrectArray) {
        index = 1;
        width = testPreCorrActiveArraySize[2];
        height = testPreCorrActiveArraySize[3];
    }
@@ -254,6 +252,19 @@ void subScaleCoordinatesTest(bool usePreCorrectArray) {
    for (size_t i = 0; i < coords.size(); i++) {
        EXPECT_LE(std::abs(coords[i] - expectedZoomOutCoords[i]), kMaxAllowedPixelError);
    }

    // Verify region zoom scaling doesn't generate invalid metering region
    // (width < 0, or height < 0)
    std::array<float, 3> scaleRatios = {10.0f, 1.0f, 0.1f};
    for (float scaleRatio : scaleRatios) {
        for (size_t i = 0; i < originalCoords.size(); i+= 2) {
            int32_t coordinates[] = {originalCoords[i], originalCoords[i+1],
                    originalCoords[i], originalCoords[i+1]};
            mapper.scaleRegion(coordinates, scaleRatio, width, height);
            EXPECT_LE(coordinates[0], coordinates[2]);
            EXPECT_LE(coordinates[1], coordinates[3]);
        }
    }
}

TEST(ZoomRatioTest, scaleCoordinatesTest) {