QCamera3: Change the way to enable HDR+
Change the way to enable HDR+ for prototyping and for
development with Easel.
persist.camera.hdrplus.enable is the grand switch to enable HDR+. If set
to 0, HAL will not generate HDR+ outputs. If set to 1, HAL will generate
HDR+ outputs if the request meets the criteria for HDR+ request.
Set persist.camera.hdrplus.apinput to 1 if AP (HAL) provides RAW
input buffers to Easel.
HDR+ mode will be enabled when HAL receives the first request with
preview intent after stream configuration. HDR+ mode is reset to
disabled during stream configuration. When HDR+ mode is enabled,
Easel will be capturing ZSL buffers and HAL will be providing
metadata for each buffers.
Add number of raw bits to sensor mode information needed by HDR+
service.
Test: GCA on Muskie
Bug: 28636965
Change-Id: I64174c6d72c7dac630aae514ec01da4e63f18fe3
diff --git a/msm8998/QCamera2/HAL3/QCamera3HWI.cpp b/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
index 0db9e92..c874ae5 100644
--- a/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
@@ -462,6 +462,9 @@
mLinkedCameraId(0),
m_pDualCamCmdHeap(NULL),
m_pDualCamCmdPtr(NULL),
+ mHdrPlusModeEnabled(false),
+ mIsApInputUsedForHdrPlus(false),
+ mFirstPreviewIntentSeen(false),
m_bSensorHDREnabled(false)
{
getLogLevel();
@@ -932,6 +935,20 @@
LOGH("mCameraId=%d",mCameraId);
+ // Create an HDR+ client instance.
+ // TODO: detect if Easel exists instead of property.
+ bool enableHdrPlus = property_get_bool("persist.camera.hdrplus.enable",
+ false);
+ ALOGD("%s: HDR+ in Camera HAL %s.", __FUNCTION__, enableHdrPlus ?
+ "enabled" : "disabled");
+ if (enableHdrPlus) {
+ mHdrPlusClient = std::make_shared<HdrPlusClient>();
+ mIsApInputUsedForHdrPlus =
+ property_get_bool("persist.camera.hdrplus.apinput", false);
+ ALOGD("%s: HDR+ input is provided by %s.", __FUNCTION__,
+ mIsApInputUsedForHdrPlus ? "AP" : "Easel");
+ }
+
return NO_ERROR;
}
@@ -968,11 +985,7 @@
rc = mCameraHandle->ops->close_camera(mCameraHandle->camera_handle);
mCameraHandle = NULL;
- // Disconnect from HDR+ client.
- if (mHdrPlusClient != nullptr) {
- mHdrPlusClient->disconnect();
- mHdrPlusClient = nullptr;
- }
+ mHdrPlusClient = nullptr;
//reset session id to some invalid id
pthread_mutex_lock(&gCamLock);
@@ -1295,10 +1308,11 @@
}
READ_PARAM_ENTRY(mParameters, CAM_INTF_PARM_SENSOR_MODE_INFO, sensorModeInfo);
- LOGH("%s: active array size %dx%d, pixel array size %dx%d, output pixel clock %u", __FUNCTION__,
- sensorModeInfo.active_array_size.width, sensorModeInfo.active_array_size.height,
- sensorModeInfo.pixel_array_size.width, sensorModeInfo.pixel_array_size.height,
- sensorModeInfo.op_pixel_clk);
+ LOGH("%s: active array size %dx%d, pixel array size %dx%d, output pixel clock %u, "
+ "raw bits: %d", __FUNCTION__, sensorModeInfo.active_array_size.width,
+ sensorModeInfo.active_array_size.height, sensorModeInfo.pixel_array_size.width,
+ sensorModeInfo.pixel_array_size.height, sensorModeInfo.op_pixel_clk,
+ sensorModeInfo.num_raw_bits);
return rc;
}
@@ -1556,41 +1570,6 @@
pthread_mutex_lock(&mMutex);
- // Check if HDR+ is enabled.
- char hdrp_prop[PROPERTY_VALUE_MAX];
- property_get("persist.camera.hdrplus", hdrp_prop, "0");
- bool enableHdrPlus = atoi(hdrp_prop);
- if (enableHdrPlus) {
- ALOGD("%s: HDR+ in Camera HAL enabled.", __FUNCTION__);
- // Connect to HDR+ client if not yet.
- if (mHdrPlusClient == nullptr) {
- mHdrPlusClient = std::make_shared<HdrPlusClient>();
- rc = mHdrPlusClient->connect(this);
- if (rc < 0) {
- LOGE("%s: Failed to connect to HDR+ client: %s (%d).", __FUNCTION__,
- strerror(-rc), rc);
- pthread_mutex_unlock(&mMutex);
- return -ENODEV;
- }
-
- // Set static metadata.
- rc = mHdrPlusClient->setStaticMetadata(*gStaticMetadata[mCameraId]);
- if (rc < 0) {
- LOGE("%s: Failed set static metadata in HDR+ client: %s (%d).", __FUNCTION__,
- strerror(-rc), rc);
- pthread_mutex_unlock(&mMutex);
- return -ENODEV;
- }
- }
- } else {
- ALOGD("%s: HDR+ in Camera HAL disabled.", __FUNCTION__);
- // Disconnect from HDR+ client if HDR+ is not enabled.
- if (mHdrPlusClient != nullptr) {
- mHdrPlusClient->disconnect();
- mHdrPlusClient = nullptr;
- }
- }
-
// Check state
switch (mState) {
case INITIALIZED:
@@ -2459,13 +2438,12 @@
}
}
- // Initialize HDR+ Raw Source channel.
- if (mHdrPlusClient != nullptr) {
+ // Initialize HDR+ Raw Source channel if AP is providing RAW input to Easel.
+ if (mHdrPlusClient != nullptr && mIsApInputUsedForHdrPlus) {
if (isRawStreamRequested || mRawDumpChannel) {
- ALOGE("%s: Enabling HDR+ while RAW output stream is configured is not supported.",
- __FUNCTION__);
- mHdrPlusClient->disconnect();
- mHdrPlusClient = nullptr;
+ ALOGE("%s: Enabling HDR+ while RAW output stream is configured is not supported. "
+ "HDR+ RAW source channel is not created.",
+ __FUNCTION__);
} else {
cam_dimension_t rawSize = getMaxRawSize(mCameraId);
cam_feature_mask_t hdrPlusRawFeatureMask = CAM_QCOM_FEATURE_NONE;
@@ -2488,7 +2466,6 @@
}
}
-
if (mAnalysisChannel) {
cam_analysis_info_t analysisInfo;
memset(&analysisInfo, 0, sizeof(cam_analysis_info_t));
@@ -2648,6 +2625,11 @@
//Get min frame duration for this streams configuration
deriveMinFrameDuration();
+ mFirstPreviewIntentSeen = false;
+
+ // Disable HRD+ if it's enabled;
+ disableHdrPlusModeLocked();
+
// Update state
mState = CONFIGURED;
@@ -3233,7 +3215,7 @@
result.output_buffers = NULL;
result.partial_result = i->partial_result_cnt;
- if (mHdrPlusClient != nullptr) {
+ if (mHdrPlusClient != nullptr && mHdrPlusModeEnabled) {
// Notify HDR+ client about the partial metadata.
mHdrPlusClient->notifyFrameMetadata(result.frame_number, *result.result,
result.partial_result == PARTIAL_RESULT_COUNT);
@@ -3800,7 +3782,7 @@
mPendingLiveRequest--;
// For a live request, send the metadata to HDR+ client.
- if (mHdrPlusClient != nullptr) {
+ if (mHdrPlusClient != nullptr && mHdrPlusModeEnabled) {
mHdrPlusClient->notifyFrameMetadata(frameNumber, *resultMetadata,
requestIter->partial_result_cnt == PARTIAL_RESULT_COUNT);
}
@@ -4649,9 +4631,8 @@
LOGE("set_parms failed for hal version, stream info");
}
- cam_sensor_mode_info_t sensor_mode_info;
- memset(&sensor_mode_info, 0, sizeof(sensor_mode_info));
- rc = getSensorModeInfo(sensor_mode_info);
+ memset(&mSensorModeInfo, 0, sizeof(mSensorModeInfo));
+ rc = getSensorModeInfo(mSensorModeInfo);
if (rc != NO_ERROR) {
LOGE("Failed to get sensor output size");
pthread_mutex_unlock(&mMutex);
@@ -4660,8 +4641,8 @@
mCropRegionMapper.update(gCamCapability[mCameraId]->active_array_size.width,
gCamCapability[mCameraId]->active_array_size.height,
- sensor_mode_info.active_array_size.width,
- sensor_mode_info.active_array_size.height);
+ mSensorModeInfo.active_array_size.width,
+ mSensorModeInfo.active_array_size.height);
/* Set batchmode before initializing channel. Since registerBuffer
* internally initializes some of the channels, better set batchmode
@@ -4753,16 +4734,6 @@
}
}
- // Configure stream for HDR+.
- if (mHdrPlusClient != nullptr) {
- rc = configureHdrPlusStreamsLocked(sensor_mode_info);
- if (rc != OK) {
- LOGE("%s: Failed to configure HDR+ streams.", __FUNCTION__);
- pthread_mutex_unlock(&mMutex);
- goto error_exit;
- }
- }
-
// Set bundle info
rc = setBundleInfo();
if (rc < 0) {
@@ -4908,33 +4879,6 @@
}
}
- if (mHdrPlusRawSrcChannel) {
- LOGD("Starting HDR+ RAW stream");
- rc = mHdrPlusRawSrcChannel->start();
- if (rc != NO_ERROR) {
- LOGE("Error Starting HDR+ RAW Channel");
- for (List<stream_info_t *>::iterator it = mStreamInfo.begin();
- it != mStreamInfo.end(); it++) {
- QCamera3Channel *channel =
- (QCamera3Channel *)(*it)->stream->priv;
- LOGH("Stopping Processing Channel mask=%d",
- channel->getStreamTypeMask());
- channel->stop();
- }
- if (mSupportChannel)
- mSupportChannel->stop();
- if (mAnalysisChannel) {
- mAnalysisChannel->stop();
- }
- if (mRawDumpChannel) {
- mRawDumpChannel->stop();
- }
- mMetadataChannel->stop();
- pthread_mutex_unlock(&mMutex);
- goto error_exit;
- }
- }
-
if (mChannelHandle) {
rc = mCameraHandle->ops->start_channel(mCameraHandle->camera_handle,
@@ -4956,6 +4900,30 @@
mFirstConfiguration = false;
}
+ // Enable HDR+ mode for the first PREVIEW_INTENT request.
+ if (mHdrPlusClient != nullptr && !mFirstPreviewIntentSeen &&
+ meta.exists(ANDROID_CONTROL_CAPTURE_INTENT) &&
+ meta.find(ANDROID_CONTROL_CAPTURE_INTENT).data.u8[0] ==
+ ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW) {
+ rc = enableHdrPlusModeLocked();
+ if (rc != OK) {
+ LOGE("%s: Failed to configure HDR+ streams.", __FUNCTION__);
+ pthread_mutex_unlock(&mMutex);
+ return rc;
+ }
+
+ // Start HDR+ RAW source channel if AP provides RAW input buffers.
+ if (mHdrPlusRawSrcChannel) {
+ rc = mHdrPlusRawSrcChannel->start();
+ if (rc != OK) {
+ LOGE("Error Starting HDR+ RAW Channel");
+ pthread_mutex_unlock(&mMutex);
+ return rc;
+ }
+ }
+ mFirstPreviewIntentSeen = true;
+ }
+
uint32_t frameNumber = request->frame_number;
cam_stream_ID_t streamsArray;
@@ -5075,7 +5043,7 @@
HdrPlusPendingRequest pendingHdrPlusRequest = {};
// If this request has a still capture intent, try to submit an HDR+ request.
- if (mHdrPlusClient != nullptr &&
+ if (mHdrPlusClient != nullptr && mHdrPlusModeEnabled &&
mCaptureIntent == ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE) {
hdrPlusRequest = trySubmittingHdrPlusRequest(&pendingHdrPlusRequest, *request, meta);
}
@@ -13672,7 +13640,8 @@
if (!metadata.exists(ANDROID_NOISE_REDUCTION_MODE) ||
metadata.find(ANDROID_NOISE_REDUCTION_MODE).data.u8[0] !=
ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY) {
- ALOGD("%s: Not an HDR+ request: ANDROID_NOISE_REDUCTION_MODE is not HQ.", __FUNCTION__);
+ ALOGD("%s: Not an HDR+ request: ANDROID_NOISE_REDUCTION_MODE is not HQ: %d", __FUNCTION__,
+ metadata.find(ANDROID_NOISE_REDUCTION_MODE).data.u8[0]);
return false;
}
@@ -13686,6 +13655,12 @@
if (request.num_output_buffers != 1 ||
request.output_buffers[0].stream->format != HAL_PIXEL_FORMAT_BLOB) {
ALOGD("%s: Not an HDR+ request: Only Jpeg output is supported.", __FUNCTION__);
+ for (uint32_t i = 0; i < request.num_output_buffers; i++) {
+ ALOGD("%s: output_buffers[%u]: %dx%d format %d", __FUNCTION__, i,
+ request.output_buffers[0].stream->width,
+ request.output_buffers[0].stream->height,
+ request.output_buffers[0].stream->format);
+ }
return false;
}
@@ -13722,8 +13697,56 @@
return true;
}
-status_t QCamera3HardwareInterface::configureHdrPlusStreamsLocked(
- const cam_sensor_mode_info_t &sensor_mode_info)
+status_t QCamera3HardwareInterface::enableHdrPlusModeLocked()
+{
+ if (mHdrPlusClient == nullptr) {
+ ALOGD("%s: HDR+ client is not created.", __FUNCTION__);
+ return -ENODEV;
+ }
+
+ // Connect to HDR+ service
+ status_t res = mHdrPlusClient->connect(this);
+ if (res != OK) {
+ LOGE("%s: Failed to connect to HDR+ client: %s (%d).", __FUNCTION__,
+ strerror(-res), res);
+ return res;
+ }
+
+ // Set static metadata.
+ res = mHdrPlusClient->setStaticMetadata(*gStaticMetadata[mCameraId]);
+ if (res != OK) {
+ LOGE("%s: Failed set static metadata in HDR+ client: %s (%d).", __FUNCTION__,
+ strerror(-res), res);
+ mHdrPlusClient->disconnect();
+ return res;
+ }
+
+ // Configure stream for HDR+.
+ res = configureHdrPlusStreamsLocked();
+ if (res != OK) {
+ LOGE("%s: Failed to configure HDR+ streams: %s (%d)", __FUNCTION__, strerror(-res), res);
+ mHdrPlusClient->disconnect();
+ return res;
+ }
+
+ mHdrPlusModeEnabled = true;
+ ALOGD("%s: HDR+ mode enabled", __FUNCTION__);
+
+ return OK;
+}
+
+void QCamera3HardwareInterface::disableHdrPlusModeLocked()
+{
+ // Disconnect from HDR+ service.
+ if (mHdrPlusClient != nullptr && mHdrPlusModeEnabled) {
+ mHdrPlusClient->disconnect();
+ }
+
+ mHdrPlusModeEnabled = false;
+ ALOGD("%s: HDR+ mode disabled", __FUNCTION__);
+}
+
+status_t QCamera3HardwareInterface::configureHdrPlusStreamsLocked()
{
pbcamera::InputConfiguration inputConfig;
std::vector<pbcamera::StreamConfiguration> outputStreamConfigs;
@@ -13745,26 +13768,23 @@
} else {
// Sensor MIPI will send data to Easel.
inputConfig.isSensorInput = true;
- inputConfig.sensorMode.pixelArrayWidth = sensor_mode_info.pixel_array_size.width;
- inputConfig.sensorMode.pixelArrayHeight = sensor_mode_info.pixel_array_size.height;
- inputConfig.sensorMode.activeArrayWidth = sensor_mode_info.active_array_size.width;
- inputConfig.sensorMode.activeArrayHeight = sensor_mode_info.active_array_size.height;
- inputConfig.sensorMode.outputPixelClkHz = sensor_mode_info.op_pixel_clk;
+ inputConfig.sensorMode.pixelArrayWidth = mSensorModeInfo.pixel_array_size.width;
+ inputConfig.sensorMode.pixelArrayHeight = mSensorModeInfo.pixel_array_size.height;
+ inputConfig.sensorMode.activeArrayWidth = mSensorModeInfo.active_array_size.width;
+ inputConfig.sensorMode.activeArrayHeight = mSensorModeInfo.active_array_size.height;
+ inputConfig.sensorMode.outputPixelClkHz = mSensorModeInfo.op_pixel_clk;
+ if (mSensorModeInfo.num_raw_bits != 10) {
+ ALOGE("%s: Only RAW10 is supported but this sensor mode has %d raw bits.", __FUNCTION__,
+ mSensorModeInfo.num_raw_bits);
+ return BAD_VALUE;
+ }
+
+ inputConfig.sensorMode.format = HAL_PIXEL_FORMAT_RAW10;
}
// Get output configurations.
// Easel may need to output RAW16 buffers if mRawChannel was created.
- if (mRawChannel != nullptr) {
- pbcamera::StreamConfiguration outputConfig;
- res = fillPbStreamConfig(&outputConfig, kPbRaw16OutputStreamId,
- HAL_PIXEL_FORMAT_RAW16, mRawChannel, /*stream index*/0);
- if (res != OK) {
- LOGE("%s: Failed to get fill stream config for raw stream: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- return res;
- }
- outputStreamConfigs.push_back(outputConfig);
- }
+ // TODO: handle RAW16 outputs.
// Easel may need to output YUV output buffers if mPictureChannel was created.
pbcamera::StreamConfiguration yuvOutputConfig;