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

Commit 4f6fa9da authored by Shuzhen Wang's avatar Shuzhen Wang
Browse files

Camera: Clarify multi-camera RAW and FOV behaviors

- RAW capability can exist for multi-camera even if physical cameras are
of different sizes/capabilities.
- FOV for all processes streams must be the same regardless of logical
or physical streams.
- All metadata tags related to pixelArray/preCorrectionActiveArray/activeArray
needs to be mapped properly by the camera HAL.
- Do distortion correction mapping for physical subcamera as well.

Test: Build and read docs, camera CTS, ITS.
Bug: 118906351
Bug: 126220135

Change-Id: I29a61fc3a603561c1d74dc2261600ce4cd3d34cd
parent 019b2fc5
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -7670,6 +7670,24 @@ typedef enum acamera_metadata_enum_acamera_request_available_capabilities {
     * <li>ACAMERA_LENS_POSE_REFERENCE</li>
     * <li>ACAMERA_LENS_DISTORTION</li>
     * </ul>
     * <p>The field of view of all non-RAW physical streams must be the same or as close as
     * possible to that of non-RAW logical streams. If the requested FOV is outside of the
     * range supported by the physical camera, the physical stream for that physical camera
     * will use either the maximum or minimum scaler crop region, depending on which one is
     * closer to the requested FOV. For example, for a logical camera with wide-tele lens
     * configuration where the wide lens is the default, if the logical camera's crop region
     * is set to maximum, the physical stream for the tele lens will be configured to its
     * maximum crop region. On the other hand, if the logical camera has a normal-wide lens
     * configuration where the normal lens is the default, when the logical camera's crop
     * region is set to maximum, the FOV of the logical streams will be that of the normal
     * lens. The FOV of the physical streams for the wide lens will be the same as the
     * logical stream, by making the crop region smaller than its active array size to
     * compensate for the smaller focal length.</p>
     * <p>Even if the underlying physical cameras have different RAW characteristics (such as
     * size or CFA pattern), a logical camera can still advertise RAW capability. In this
     * case, when the application configures a RAW stream, the camera device will make sure
     * the active physical camera will remain active to ensure consistent RAW output
     * behavior, and not switch to other physical cameras.</p>
     * <p>To maintain backward compatibility, the capture request and result metadata tags
     * required for basic camera functionalities will be solely based on the
     * logical camera capabiltity. Other request and result metadata tags, on the other
+44 −10
Original line number Diff line number Diff line
@@ -132,13 +132,24 @@ status_t Camera3Device::initialize(sp<CameraProviderManager> manager, const Stri
    bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
    if (isLogical) {
        for (auto& physicalId : physicalCameraIds) {
            res = manager->getCameraCharacteristics(physicalId, &mPhysicalDeviceInfoMap[physicalId]);
            res = manager->getCameraCharacteristics(
                    physicalId, &mPhysicalDeviceInfoMap[physicalId]);
            if (res != OK) {
                SET_ERR_L("Could not retrieve camera %s characteristics: %s (%d)",
                        physicalId.c_str(), strerror(-res), res);
                session->close();
                return res;
            }

            if (DistortionMapper::isDistortionSupported(mPhysicalDeviceInfoMap[physicalId])) {
                mDistortionMappers[physicalId].setupStaticInfo(mPhysicalDeviceInfoMap[physicalId]);
                if (res != OK) {
                    SET_ERR_L("Unable to read camera %s's calibration fields for distortion "
                            "correction", physicalId.c_str());
                    session->close();
                    return res;
                }
            }
        }
    }

@@ -308,7 +319,7 @@ status_t Camera3Device::initializeCommonLocked() {
    }

    if (DistortionMapper::isDistortionSupported(mDeviceInfo)) {
        res = mDistortionMapper.setupStaticInfo(mDeviceInfo);
        res = mDistortionMappers[mId.c_str()].setupStaticInfo(mDeviceInfo);
        if (res != OK) {
            SET_ERR_L("Unable to read necessary calibration fields for distortion correction");
            return res;
@@ -3503,12 +3514,27 @@ void Camera3Device::sendCaptureResult(CameraMetadata &pendingMetadata,
    }

    // Fix up some result metadata to account for HAL-level distortion correction
    status_t res = mDistortionMapper.correctCaptureResult(&captureResult.mMetadata);
    status_t res =
            mDistortionMappers[mId.c_str()].correctCaptureResult(&captureResult.mMetadata);
    if (res != OK) {
        SET_ERR("Unable to correct capture result metadata for frame %d: %s (%d)",
                frameNumber, strerror(res), res);
        return;
    }
    for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
        String8 cameraId8(physicalMetadata.mPhysicalCameraId);
        if (mDistortionMappers.find(cameraId8.c_str()) == mDistortionMappers.end()) {
            continue;
        }
        res = mDistortionMappers[cameraId8.c_str()].correctCaptureResult(
                &physicalMetadata.mPhysicalCameraMetadata);
        if (res != OK) {
            SET_ERR("Unable to correct physical capture result metadata for frame %d: %s (%d)",
                    frameNumber, strerror(res), res);
            return;
        }
    }

    // Fix up result metadata for monochrome camera.
    res = fixupMonochromeTags(mDeviceInfo, captureResult.mMetadata);
    if (res != OK) {
@@ -5481,8 +5507,15 @@ status_t Camera3Device::RequestThread::prepareHalRequests() {
                // Correct metadata regions for distortion correction if enabled
                sp<Camera3Device> parent = mParent.promote();
                if (parent != nullptr) {
                    res = parent->mDistortionMapper.correctCaptureRequest(
                        &(captureRequest->mSettingsList.begin()->metadata));
                    List<PhysicalCameraSettings>::iterator it;
                    for (it = captureRequest->mSettingsList.begin();
                            it != captureRequest->mSettingsList.end(); it++) {
                        if (parent->mDistortionMappers.find(it->cameraId) ==
                                parent->mDistortionMappers.end()) {
                            continue;
                        }
                        res = parent->mDistortionMappers[it->cameraId].correctCaptureRequest(
                            &(it->metadata));
                        if (res != OK) {
                            SET_ERR("RequestThread: Unable to correct capture requests "
                                    "for lens distortion for request %d: %s (%d)",
@@ -5491,6 +5524,7 @@ status_t Camera3Device::RequestThread::prepareHalRequests() {
                        }
                    }
                }
            }

            /**
             * The request should be presorted so accesses in HAL
+4 −2
Original line number Diff line number Diff line
@@ -1250,8 +1250,10 @@ class Camera3Device :
    /**
     * Distortion correction support
     */

    camera3::DistortionMapper mDistortionMapper;
    // Map from camera IDs to its corresponding distortion mapper. Only contains
    // 1 ID if the device isn't a logical multi-camera. Otherwise contains both
    // logical camera and its physical subcameras.
    std::unordered_map<std::string, camera3::DistortionMapper> mDistortionMappers;

    // Debug tracker for metadata tag value changes
    // - Enabled with the -m <taglist> option to dumpsys, such as