Loading services/camera/libcameraservice/device3/Camera3OutputUtils.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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); } Loading services/camera/libcameraservice/device3/ZoomRatioMapper.cpp +20 −20 Original line number Diff line number Diff line Loading @@ -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; } } Loading Loading @@ -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) { Loading Loading @@ -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) { Loading services/camera/libcameraservice/device3/ZoomRatioMapper.h +2 −0 Original line number Diff line number Diff line Loading @@ -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: Loading services/camera/libcameraservice/tests/ZoomRatioTest.cpp +13 −2 Original line number Diff line number Diff line Loading @@ -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]; } Loading Loading @@ -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) { Loading Loading
services/camera/libcameraservice/device3/Camera3OutputUtils.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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); } Loading
services/camera/libcameraservice/device3/ZoomRatioMapper.cpp +20 −20 Original line number Diff line number Diff line Loading @@ -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; } } Loading Loading @@ -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) { Loading Loading @@ -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) { Loading
services/camera/libcameraservice/device3/ZoomRatioMapper.h +2 −0 Original line number Diff line number Diff line Loading @@ -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: Loading
services/camera/libcameraservice/tests/ZoomRatioTest.cpp +13 −2 Original line number Diff line number Diff line Loading @@ -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]; } Loading Loading @@ -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) { Loading