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

Commit 91f4a9b9 authored by Kwangkyu Park's avatar Kwangkyu Park
Browse files

Camera: Apply max batch size for high speed video

Currently, capture requests are batch-sized based on 'max fps/preview
fps' for the high speed video. It normally works to achieve efficient
high speed video recording as it is the allowed maximum value.

However, aggregating multiple requests will scarifice performance for
some specific SoCs. They report batch_size_max in the
'availableHighSpeedVideoConfigurations', but the value is honored
nowhere in camera framework.

This patch breaks down the request list based on the reported
batch_size_max.

Bug: 274392420
Test: CameraCTS
Change-Id: I1c0bbad736d0ce70369a18fbd82c034d38b68568
parent 6999bc03
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@ enum SystemCameraKind {
};

#define CAMERA_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION(1, 0)
#define CAMERA_DEVICE_API_VERSION_1_2 HARDWARE_DEVICE_API_VERSION(1, 2)
#define CAMERA_DEVICE_API_VERSION_3_0 HARDWARE_DEVICE_API_VERSION(3, 0)
#define CAMERA_DEVICE_API_VERSION_3_1 HARDWARE_DEVICE_API_VERSION(3, 1)
#define CAMERA_DEVICE_API_VERSION_3_2 HARDWARE_DEVICE_API_VERSION(3, 2)
+2 −2
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@
#include <cutils/properties.h>
#include <camera/StringUtils.h>

#include <android-base/properties.h>
#include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
#include <android/hardware/camera2/ICameraDeviceUser.h>

@@ -756,8 +757,7 @@ status_t Camera3Device::convertMetadataListToRequestListLocked(
        auto firstRequest = requestList->begin();
        for (auto& outputStream : (*firstRequest)->mOutputStreams) {
            if (outputStream->isVideoStream()) {
                (*firstRequest)->mBatchSize = requestList->size();
                outputStream->setBatchSize(requestList->size());
                applyMaxBatchSizeLocked(requestList, outputStream);
                break;
            }
        }
+9 −0
Original line number Diff line number Diff line
@@ -655,6 +655,15 @@ class Camera3Device :
     */
    status_t initializeCommonLocked();

    /**
     * Update capture request list so that each batch size honors the batch_size_max report from
     * the HAL. Set the batch size to output stream for buffer operations.
     *
     * Must be called with mLock held.
     */
    virtual void applyMaxBatchSizeLocked(
            RequestList* requestList, const sp<camera3::Camera3OutputStreamInterface>& stream) = 0;

    /**
     * Get the last request submitted to the hal by the request thread.
     *
+75 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@

#include <aidl/android/hardware/camera/device/ICameraInjectionSession.h>
#include <aidlcommonsupport/NativeHandle.h>
#include <android-base/properties.h>
#include <android/binder_ibinder_platform.h>
#include <android/hardware/camera2/ICameraDeviceUser.h>
#include <camera/StringUtils.h>
@@ -309,6 +310,20 @@ status_t AidlCamera3Device::initialize(sp<CameraProviderManager> manager,
        }
    }

    // batch size limit is applied to the device with camera device version larger than 3.2 which is
    // AIDL v2
    hardware::hidl_version maxVersion{0, 0};
    IPCTransport transport = IPCTransport::AIDL;
    res = manager->getHighestSupportedVersion(mId, &maxVersion, &transport);
    if (res != OK) {
        ALOGE("%s: Error in getting camera device version id: %s (%d)", __FUNCTION__,
              strerror(-res), res);
        return res;
    }
    int deviceVersion = HARDWARE_DEVICE_API_VERSION(maxVersion.get_major(), maxVersion.get_minor());

    mBatchSizeLimitEnabled = (deviceVersion >= CAMERA_DEVICE_API_VERSION_1_2);

    return initializeCommonLocked();
}

@@ -1572,6 +1587,66 @@ status_t AidlCamera3Device::AidlCamera3DeviceInjectionMethods::replaceHalInterfa
    return OK;
}

void AidlCamera3Device::applyMaxBatchSizeLocked(
        RequestList* requestList, const sp<camera3::Camera3OutputStreamInterface>& stream) {
    int batchSize = requestList->size();

    if (!mBatchSizeLimitEnabled) {
        (*requestList->begin())->mBatchSize = batchSize;
        stream->setBatchSize(batchSize);
        return;
    }

    const auto& metadata = (*requestList->begin())->mSettingsList.begin()->metadata;

    uint32_t tag = ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS;
    auto sensorPixelModeEntry = metadata.find(ANDROID_SENSOR_PIXEL_MODE);
    if (sensorPixelModeEntry.count != 0) {
        if (ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION == sensorPixelModeEntry.data.u8[0]) {
            tag = ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS_MAXIMUM_RESOLUTION;
        }
    }

    const auto fpsRange = metadata.find(ANDROID_CONTROL_AE_TARGET_FPS_RANGE);
    if (fpsRange.count > 1) {
        auto configEntry = mDeviceInfo.find(tag);
        for (size_t index = 4; index < configEntry.count; index += 5) {
            if (stream->getWidth() == static_cast<uint32_t>(configEntry.data.i32[index - 4]) &&
                stream->getHeight() == static_cast<uint32_t>(configEntry.data.i32[index - 3]) &&
                fpsRange.data.i32[0] == configEntry.data.i32[index - 2] &&
                fpsRange.data.i32[1] == configEntry.data.i32[index - 1]) {
                const int maxBatchSize = configEntry.data.i32[index - 1] / 30;
                const int reportedSize = configEntry.data.i32[index];

                if (maxBatchSize % reportedSize == 0 && requestList->size() % reportedSize == 0) {
                    batchSize = reportedSize;
                    ALOGVV("Matching high speed configuration found. Limit batch size to %d",
                           batchSize);
                } else if (maxBatchSize % reportedSize == 0 &&
                           reportedSize % requestList->size() == 0) {
                    ALOGVV("Matching high speed configuration found, but requested batch size is "
                           "divisor of batch_size_max. No need to limit batch size.");
                } else {
                    ALOGW("Matching high speed configuration found, but batch_size_max is not a "
                          "divisor of corresponding fps_max/30 or requested batch size is not a "
                          "divisor of batch_size_max, (fps_max %d, batch_size_max %d, requested "
                          "batch size %zu)",
                          configEntry.data.i32[index - 1], reportedSize, requestList->size());
                }
                break;
            }
        }
    }

    for (auto request = requestList->begin(); request != requestList->end(); request++) {
        if (requestList->distance(requestList->begin(), request) % batchSize == 0) {
            (*request)->mBatchSize = batchSize;
        }
    }

    stream->setBatchSize(batchSize);
}

status_t AidlCamera3Device::injectionCameraInitialize(const std::string &injectedCamId,
            sp<CameraProviderManager> manager) {
        return (static_cast<AidlCamera3DeviceInjectionMethods *>
+7 −0
Original line number Diff line number Diff line
@@ -252,6 +252,10 @@ class AidlCamera3Device :
    };

  private:
    virtual void applyMaxBatchSizeLocked(
            RequestList* requestList,
            const sp<camera3::Camera3OutputStreamInterface>& stream) override;

    virtual status_t injectionCameraInitialize(const std::string &injectCamId,
            sp<CameraProviderManager> manager) override;

@@ -271,6 +275,9 @@ class AidlCamera3Device :

    std::shared_ptr<AidlCameraDeviceCallbacks> mCallbacks = nullptr;

    // Whether the batch_size_max field in the high speed configuration actually applied to
    // capture requests.
    bool mBatchSizeLimitEnabled = false;

}; // class AidlCamera3Device

Loading