QCamera3: Refactor HDR+ stream config and request
Move HDR+ stream configuration and HDR+ capture request to its own
functions.
Test: camera2hdr with HDR+ enabled
Bug: 28637032
Change-Id: Id8f8ee123a0cf5dd2072aed960f76ba0261f6152
diff --git a/msm8998/QCamera2/HAL3/QCamera3HWI.cpp b/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
index df67247..223ea60 100644
--- a/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
@@ -4500,73 +4500,11 @@
}
}
+ // Configure stream for HDR+.
if (mHdrPlusClient != nullptr) {
- pbcamera::InputConfiguration inputConfig;
- std::vector<pbcamera::StreamConfiguration> outputStreamConfigs;
-
- // Configure HDR+ client streams.
- // Get input config.
- if (mHdrPlusRawSrcChannel) {
- // HDR+ input buffers will be provided by HAL.
- rc = fillPbStreamConfig(&inputConfig.streamConfig, kPbRaw10InputStreamId,
- HAL_PIXEL_FORMAT_RAW10, mHdrPlusRawSrcChannel, /*stream index*/0);
- if (rc != OK) {
- LOGE("%s: Failed to get fill stream config for HDR+ raw src stream.",
- __FUNCTION__);
- pthread_mutex_unlock(&mMutex);
- goto error_exit;
- }
-
- inputConfig.isSensorInput = false;
- } 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;
- }
-
- // Get output configurations.
- // Easel may need to output RAW16 buffers if mRawChannel was created.
- if (mRawChannel != nullptr) {
- pbcamera::StreamConfiguration outputConfig;
- rc = fillPbStreamConfig(&outputConfig, kPbRaw16OutputStreamId,
- HAL_PIXEL_FORMAT_RAW16, mRawChannel, /*stream index*/0);
- if (rc != OK) {
- LOGE("%s: Failed to get fill stream config for raw stream.", __FUNCTION__);
- pthread_mutex_unlock(&mMutex);
- goto error_exit;
- }
- outputStreamConfigs.push_back(outputConfig);
- }
-
- // Easel may need to output YUV output buffers if mPictureChannel was created.
- if (mPictureChannel != nullptr) {
- pbcamera::StreamConfiguration outputConfig;
- rc = fillPbStreamConfig(&outputConfig, kPbYuvOutputStreamId,
- HAL_PIXEL_FORMAT_YCrCb_420_SP, mPictureChannel, /*stream index*/0);
- if (rc != OK) {
- LOGE("%s: Failed to get fill stream config for YUV stream.", __FUNCTION__);
- pthread_mutex_unlock(&mMutex);
- goto error_exit;
- }
-
- outputStreamConfigs.push_back(outputConfig);
- }
-
- // TODO: consider other channels for YUV output buffers.
-
- rc = mHdrPlusClient->configureStreams(inputConfig, outputStreamConfigs);
+ rc = configureHdrPlusStreamsLocked(sensor_mode_info);
if (rc != OK) {
- LOGE("%d: Failed to configure streams with HDR+ client: %s (%d)", __FUNCTION__,
- strerror(-rc), rc);
+ LOGE("%s: Failed to configure HDR+ streams.", __FUNCTION__);
pthread_mutex_unlock(&mMutex);
goto error_exit;
}
@@ -4876,67 +4814,10 @@
bool hdrPlusRequest = false;
HdrPlusPendingRequest pendingHdrPlusRequest = {};
- // Decide if this is an HDR+ capture request.
+ // If this request has a still capture intent, try to submit an HDR+ request.
if (mHdrPlusClient != nullptr &&
- mCaptureIntent == ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE) {
- bool highQualityPostProcessing = true;
-
- // Check noise reduction mode is high quality.
- if (!meta.exists(ANDROID_NOISE_REDUCTION_MODE) ||
- meta.find(ANDROID_NOISE_REDUCTION_MODE).data.u8[0] !=
- ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY) {
- highQualityPostProcessing = false;
- }
-
- // Check edge mode is high quality.
- if (!meta.exists(ANDROID_EDGE_MODE) ||
- meta.find(ANDROID_EDGE_MODE).data.u8[0] !=
- ANDROID_EDGE_MODE_HIGH_QUALITY) {
- highQualityPostProcessing = false;
- }
-
- // If all post processing is high quality, this still capture request is an HDR+ request.
- // TODO: support more than a single JPEG output buffer.
- if (highQualityPostProcessing && request->num_output_buffers == 1 &&
- request->output_buffers[0].stream->format == HAL_PIXEL_FORMAT_BLOB) {
- auto frame = std::make_shared<mm_camera_buf_def_t>();
-
- // Get a YUV buffer from pic channel.
- QCamera3PicChannel *picChannel =
- (QCamera3PicChannel*)request->output_buffers[0].stream->priv;
- rc = picChannel->getYuvBufferForRequest(frame.get(), frameNumber);
- if (rc != OK) {
- ALOGE("%s: Getting an available YUV buffer from pic channel failed: %s (%d)",
- __FUNCTION__, strerror(-rc), rc);
- pthread_mutex_unlock(&mMutex);
- return rc;
- }
-
- pbcamera::StreamBuffer buffer;
- buffer.streamId = kPbYuvOutputStreamId;
- buffer.data = frame->buffer;
- buffer.dataSize = frame->frame_len;
-
- pbcamera::CaptureRequest pbRequest;
- pbRequest.id = frameNumber;
- pbRequest.outputBuffers.push_back(buffer);
-
- // Submit an HDR+ capture request to HDR+ service.
- rc = mHdrPlusClient->submitCaptureRequest(&pbRequest);
- if (rc != OK) {
- ALOGE("%s: %d: Submitting a capture request failed: %s (%d)", __FUNCTION__,
- __LINE__, strerror(-rc), rc);
- }
-
- hdrPlusRequest = true;
-
- pendingHdrPlusRequest.yuvBuffer = frame;
- pendingHdrPlusRequest.frameworkOutputBuffers.push_back(request->output_buffers[0]);
- } else {
- ALOGD("%s: Fall back to non HDR+ capture request. high quality: %d, number of "
- "output buffers: %d", __FUNCTION__, highQualityPostProcessing,
- request->num_output_buffers);
- }
+ mCaptureIntent == ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE) {
+ hdrPlusRequest = trySubmittingHdrPlusRequest(&pendingHdrPlusRequest, *request, meta);
}
if (hdrPlusRequest) {
@@ -13152,6 +13033,136 @@
}
}
+bool QCamera3HardwareInterface::trySubmittingHdrPlusRequest(HdrPlusPendingRequest *hdrPlusRequest,
+ const camera3_capture_request_t &request, const CameraMetadata &metadata)
+{
+ if (hdrPlusRequest == nullptr) return false;
+
+ // Check noise reduction mode is high quality.
+ 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__);
+ return false;
+ }
+
+ // Check edge mode is high quality.
+ if (!metadata.exists(ANDROID_EDGE_MODE) ||
+ metadata.find(ANDROID_EDGE_MODE).data.u8[0] != ANDROID_EDGE_MODE_HIGH_QUALITY) {
+ ALOGD("%s: Not an HDR+ request: ANDROID_EDGE_MODE is not HQ.", __FUNCTION__);
+ return false;
+ }
+
+ 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__);
+ return false;
+ }
+
+ // Get a YUV buffer from pic channel.
+ QCamera3PicChannel *picChannel = (QCamera3PicChannel*)request.output_buffers[0].stream->priv;
+ auto yuvBuffer = std::make_shared<mm_camera_buf_def_t>();
+ status_t res = picChannel->getYuvBufferForRequest(yuvBuffer.get(), request.frame_number);
+ if (res != OK) {
+ ALOGE("%s: Getting an available YUV buffer from pic channel failed: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return false;
+ }
+
+ pbcamera::StreamBuffer buffer;
+ buffer.streamId = kPbYuvOutputStreamId;
+ buffer.data = yuvBuffer->buffer;
+ buffer.dataSize = yuvBuffer->frame_len;
+
+ pbcamera::CaptureRequest pbRequest;
+ pbRequest.id = request.frame_number;
+ pbRequest.outputBuffers.push_back(buffer);
+
+ // Submit an HDR+ capture request to HDR+ service.
+ res = mHdrPlusClient->submitCaptureRequest(&pbRequest);
+ if (res != OK) {
+ ALOGE("%s: %d: Submitting a capture request failed: %s (%d)", __FUNCTION__, __LINE__,
+ strerror(-res), res);
+ return false;
+ }
+
+ hdrPlusRequest->yuvBuffer = yuvBuffer;
+ hdrPlusRequest->frameworkOutputBuffers.push_back(request.output_buffers[0]);
+
+ return true;
+}
+
+status_t QCamera3HardwareInterface::configureHdrPlusStreamsLocked(
+ const cam_sensor_mode_info_t &sensor_mode_info)
+{
+ pbcamera::InputConfiguration inputConfig;
+ std::vector<pbcamera::StreamConfiguration> outputStreamConfigs;
+ status_t res = OK;
+
+ // Configure HDR+ client streams.
+ // Get input config.
+ if (mHdrPlusRawSrcChannel) {
+ // HDR+ input buffers will be provided by HAL.
+ res = fillPbStreamConfig(&inputConfig.streamConfig, kPbRaw10InputStreamId,
+ HAL_PIXEL_FORMAT_RAW10, mHdrPlusRawSrcChannel, /*stream index*/0);
+ if (res != OK) {
+ LOGE("%s: Failed to get fill stream config for HDR+ raw src stream: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return res;
+ }
+
+ inputConfig.isSensorInput = false;
+ } 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;
+ }
+
+ // 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);
+ }
+
+ // Easel may need to output YUV output buffers if mPictureChannel was created.
+ pbcamera::StreamConfiguration yuvOutputConfig;
+ if (mPictureChannel != nullptr) {
+ res = fillPbStreamConfig(&yuvOutputConfig, kPbYuvOutputStreamId,
+ HAL_PIXEL_FORMAT_YCrCb_420_SP, mPictureChannel, /*stream index*/0);
+ if (res != OK) {
+ LOGE("%s: Failed to get fill stream config for YUV stream: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+
+ return res;
+ }
+
+ outputStreamConfigs.push_back(yuvOutputConfig);
+ }
+
+ // TODO: consider other channels for YUV output buffers.
+
+ res = mHdrPlusClient->configureStreams(inputConfig, outputStreamConfigs);
+ if (res != OK) {
+ LOGE("%d: Failed to configure streams with HDR+ client: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ return res;
+ }
+
+ return OK;
+}
+
void QCamera3HardwareInterface::onCaptureResult(pbcamera::CaptureResult *result,
const camera_metadata_t &resultMetadata) {
if (result != nullptr) {