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
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 98298ea..7f3130e 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -86,6 +86,7 @@
};
#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)
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index f7a3cc7..12cbbf6 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -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 @@
auto firstRequest = requestList->begin();
for (auto& outputStream : (*firstRequest)->mOutputStreams) {
if (outputStream->isVideoStream()) {
- (*firstRequest)->mBatchSize = requestList->size();
- outputStream->setBatchSize(requestList->size());
+ applyMaxBatchSizeLocked(requestList, outputStream);
break;
}
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 7b89f9f..6236c7e 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -656,6 +656,15 @@
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.
*
* Must be called with mLock held.
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
index 1f9313e..1f2ac23 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
@@ -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 @@
}
}
+ // 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 @@
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 *>
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
index f4554d4..4d7d139 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
@@ -252,6 +252,10 @@
};
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 @@
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
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
index c22aad6..d234d83 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
@@ -699,6 +699,14 @@
// Java side to make sure the CameraCaptureSession is properly closed
}
+void HidlCamera3Device::applyMaxBatchSizeLocked(
+ RequestList* requestList, const sp<camera3::Camera3OutputStreamInterface>& stream) {
+ int batchSize = requestList->size();
+
+ (*requestList->begin())->mBatchSize = batchSize;
+ stream->setBatchSize(batchSize);
+}
+
sp<Camera3Device::RequestThread> HidlCamera3Device::createNewRequestThread(
wp<Camera3Device> parent, sp<camera3::StatusTracker> statusTracker,
sp<Camera3Device::HalInterface> interface,
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
index e64bcf0..2d33277 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
@@ -213,6 +213,10 @@
hardware::Return<void> notifyHelper(
const hardware::hidl_vec<NotifyMsgType>& msgs);
+ virtual void applyMaxBatchSizeLocked(
+ RequestList* requestList,
+ const sp<camera3::Camera3OutputStreamInterface>& stream) override;
+
virtual status_t injectionCameraInitialize(const std::string &injectCamId,
sp<CameraProviderManager> manager) override;