Camera: Add 10-bit dynamic range support
Check for supported 10-bit dynamic range profiles during
stream configuration.
When needed, verify incoming process requests for unsupported
dynamic range profile combinations.
Propagate HDR metadata to corresponding registered native windows.
Bug: 195946346
Test: Camera CTS
Change-Id: I3d47418e8186959d7d1772d037755c20f8f37e74
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 2f571a6..4c1e7f0 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -531,6 +531,12 @@
return measured;
}
+CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap
+Camera3Device::mapToHidlDynamicProfile(int dynamicRangeProfile) {
+ return static_cast<CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap>(
+ dynamicRangeProfile);
+}
+
hardware::graphics::common::V1_0::PixelFormat Camera3Device::mapToPixelFormat(
int frameworkFormat) {
return (hardware::graphics::common::V1_0::PixelFormat) frameworkFormat;
@@ -1384,7 +1390,7 @@
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
- uint64_t consumerUsage) {
+ uint64_t consumerUsage, int dynamicRangeProfile) {
ATRACE_CALL();
if (consumer == nullptr) {
@@ -1397,7 +1403,7 @@
return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
format, dataSpace, rotation, id, physicalCameraId, sensorPixelModesUsed, surfaceIds,
- streamSetId, isShared, isMultiResolution, consumerUsage);
+ streamSetId, isShared, isMultiResolution, consumerUsage, dynamicRangeProfile);
}
static bool isRawFormat(int format) {
@@ -1417,7 +1423,7 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
const String8& physicalCameraId, const std::unordered_set<int32_t> &sensorPixelModesUsed,
std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
- uint64_t consumerUsage) {
+ uint64_t consumerUsage, int dynamicRangeProfile) {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
@@ -1495,7 +1501,7 @@
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, blobBufferSize, format, dataSpace, rotation,
mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
- isMultiResolution);
+ isMultiResolution, dynamicRangeProfile);
} else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
bool maxResolution =
sensorPixelModesUsed.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
@@ -1509,22 +1515,22 @@
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
- isMultiResolution);
+ isMultiResolution, dynamicRangeProfile);
} else if (isShared) {
newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
width, height, format, consumerUsage, dataSpace, rotation,
mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
- mUseHalBufManager);
+ mUseHalBufManager, dynamicRangeProfile);
} else if (consumers.size() == 0 && hasDeferredConsumer) {
newStream = new Camera3OutputStream(mNextStreamId,
width, height, format, consumerUsage, dataSpace, rotation,
mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
- isMultiResolution);
+ isMultiResolution, dynamicRangeProfile);
} else {
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, format, dataSpace, rotation,
mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
- isMultiResolution);
+ isMultiResolution, dynamicRangeProfile);
}
size_t consumerCount = consumers.size();
@@ -1611,6 +1617,7 @@
streamInfo->originalFormat = stream->getOriginalFormat();
streamInfo->dataSpaceOverridden = stream->isDataSpaceOverridden();
streamInfo->originalDataSpace = stream->getOriginalDataSpace();
+ streamInfo->dynamicRangeProfile = stream->getDynamicRangeProfile();
return OK;
}
@@ -2223,7 +2230,8 @@
streamStats.emplace_back(stream->getWidth(), stream->getHeight(),
stream->getFormat(), stream->getDataSpace(), usage,
stream->getMaxHalBuffers(),
- stream->getMaxTotalBuffers() - stream->getMaxHalBuffers());
+ stream->getMaxTotalBuffers() - stream->getMaxHalBuffers(),
+ stream->getDynamicRangeProfile());
}
}
}
@@ -3144,6 +3152,10 @@
mSupportOfflineProcessing(supportOfflineProcessing) {
// Check with hardware service manager if we can downcast these interfaces
// Somewhat expensive, so cache the results at startup
+ auto castResult_3_8 = device::V3_8::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_8.isOk()) {
+ mHidlSession_3_8 = castResult_3_8;
+ }
auto castResult_3_7 = device::V3_7::ICameraDeviceSession::castFrom(mHidlSession);
if (castResult_3_7.isOk()) {
mHidlSession_3_7 = castResult_3_7;
@@ -3181,6 +3193,7 @@
}
void Camera3Device::HalInterface::clear() {
+ mHidlSession_3_8.clear();
mHidlSession_3_7.clear();
mHidlSession_3_6.clear();
mHidlSession_3_5.clear();
@@ -3318,13 +3331,16 @@
device::V3_2::StreamConfiguration requestedConfiguration3_2;
device::V3_4::StreamConfiguration requestedConfiguration3_4;
device::V3_7::StreamConfiguration requestedConfiguration3_7;
+ device::V3_8::StreamConfiguration requestedConfiguration3_8;
requestedConfiguration3_2.streams.resize(config->num_streams);
requestedConfiguration3_4.streams.resize(config->num_streams);
requestedConfiguration3_7.streams.resize(config->num_streams);
+ requestedConfiguration3_8.streams.resize(config->num_streams);
for (size_t i = 0; i < config->num_streams; i++) {
device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
device::V3_7::Stream &dst3_7 = requestedConfiguration3_7.streams[i];
+ device::V3_8::Stream &dst3_8 = requestedConfiguration3_8.streams[i];
camera3::camera_stream_t *src = config->streams[i];
Camera3Stream* cam3stream = Camera3Stream::cast(src);
@@ -3373,6 +3389,15 @@
dst3_7.sensorPixelModesUsed[j++] =
static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
}
+ if ((src->dynamic_range_profile !=
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) &&
+ (mHidlSession_3_8 == nullptr)) {
+ ALOGE("%s: Camera device doesn't support non-standard dynamic range profiles: %d",
+ __FUNCTION__, src->dynamic_range_profile);
+ return BAD_VALUE;
+ }
+ dst3_8.v3_7 = dst3_7;
+ dst3_8.dynamicRangeProfile = mapToHidlDynamicProfile(src->dynamic_range_profile);
activeStreams.insert(streamId);
// Create Buffer ID map if necessary
mBufferRecords.tryCreateBufferCache(streamId);
@@ -3398,6 +3423,10 @@
requestedConfiguration3_7.sessionParams.setToExternal(
reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
sessionParamSize);
+ requestedConfiguration3_8.operationMode = operationMode;
+ requestedConfiguration3_8.sessionParams.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
+ sessionParamSize);
// Invoke configureStreams
device::V3_3::HalStreamConfiguration finalConfiguration;
@@ -3444,7 +3473,17 @@
};
// See which version of HAL we have
- if (mHidlSession_3_7 != nullptr) {
+ if (mHidlSession_3_8 != nullptr) {
+ ALOGV("%s: v3.8 device found", __FUNCTION__);
+ requestedConfiguration3_8.streamConfigCounter = mNextStreamConfigCounter++;
+ requestedConfiguration3_8.multiResolutionInputImage = config->input_is_multi_resolution;
+ auto err = mHidlSession_3_8->configureStreams_3_8(requestedConfiguration3_8,
+ configStream36Cb);
+ res = postprocConfigStream36(err);
+ if (res != OK) {
+ return res;
+ }
+ } else if (mHidlSession_3_7 != nullptr) {
ALOGV("%s: v3.7 device found", __FUNCTION__);
requestedConfiguration3_7.streamConfigCounter = mNextStreamConfigCounter++;
requestedConfiguration3_7.multiResolutionInputImage = config->input_is_multi_resolution;
@@ -4052,6 +4091,18 @@
return OK;
}
+status_t Camera3Device::HalInterface::repeatingRequestEnd(uint32_t frameNumber,
+ hardware::hidl_vec<int32_t> streamIds) {
+ ATRACE_NAME("CameraHal::repeatingRequestEnd");
+ if (!valid()) return INVALID_OPERATION;
+
+ if (mHidlSession_3_8.get() != nullptr) {
+ mHidlSession_3_8->repeatingRequestEnd(frameNumber, streamIds);
+ }
+
+ return OK;
+}
+
status_t Camera3Device::HalInterface::close() {
ATRACE_NAME("CameraHal::close()");
if (!valid()) return INVALID_OPERATION;
@@ -4386,10 +4437,20 @@
}
status_t Camera3Device::RequestThread::clearRepeatingRequestsLocked(/*out*/int64_t *lastFrameNumber) {
+ std::vector<int32_t> streamIds;
+ for (const auto& request : mRepeatingRequests) {
+ for (const auto& stream : request->mOutputStreams) {
+ streamIds.push_back(stream->getId());
+ }
+ }
+
mRepeatingRequests.clear();
if (lastFrameNumber != NULL) {
*lastFrameNumber = mRepeatingLastFrameNumber;
}
+
+ mInterface->repeatingRequestEnd(mRepeatingLastFrameNumber, streamIds);
+
mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
return OK;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 3f069f9..3ce17f9 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -36,6 +36,7 @@
#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.6/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.7/ICameraDeviceSession.h>
+#include <android/hardware/camera/device/3.8/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.2/ICameraDeviceCallback.h>
#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
@@ -44,6 +45,7 @@
#include <camera/CaptureResult.h>
+#include "android/hardware/camera/metadata/3.8/types.h"
#include "common/CameraDeviceBase.h"
#include "device3/BufferUtils.h"
#include "device3/StatusTracker.h"
@@ -68,6 +70,7 @@
using android::camera3::camera_stream_configuration_mode_t;
using android::camera3::CAMERA_TEMPLATE_COUNT;
using android::camera3::OutputStreamInfo;
+using android::hardware::camera::metadata::V3_8::CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap;
namespace android {
@@ -141,7 +144,9 @@
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, bool isMultiResolution = false,
- uint64_t consumerUsage = 0) override;
+ uint64_t consumerUsage = 0,
+ int dynamicRangeProfile =
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) override;
status_t createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
@@ -151,7 +156,9 @@
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, bool isMultiResolution = false,
- uint64_t consumerUsage = 0) override;
+ uint64_t consumerUsage = 0,
+ int dynamicRangeProfile =
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) override;
status_t createInputStream(
uint32_t width, uint32_t height, int format, bool isMultiResolution,
@@ -287,6 +294,8 @@
static hardware::graphics::common::V1_0::PixelFormat mapToPixelFormat(int frameworkFormat);
static hardware::camera::device::V3_2::DataspaceFlags mapToHidlDataspace(
android_dataspace dataSpace);
+ static CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap mapToHidlDynamicProfile(
+ int dynamicRangeProfile);
static hardware::camera::device::V3_2::BufferUsageFlags mapToConsumerUsage(uint64_t usage);
static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
camera_stream_rotation_t rotation);
@@ -416,6 +425,8 @@
/*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
/*out*/camera3::BufferRecords* bufferRecords);
+ status_t repeatingRequestEnd(uint32_t frameNumber, hardware::hidl_vec<int32_t> streamIds);
+
/////////////////////////////////////////////////////////////////////
// Implements BufferRecordsInterface
@@ -458,6 +469,8 @@
sp<hardware::camera::device::V3_6::ICameraDeviceSession> mHidlSession_3_6;
// Valid if ICameraDeviceSession is @3.7 or newer
sp<hardware::camera::device::V3_7::ICameraDeviceSession> mHidlSession_3_7;
+ // Valid if ICameraDeviceSession is @3.8 or newer
+ sp<hardware::camera::device::V3_8::ICameraDeviceSession> mHidlSession_3_8;
std::shared_ptr<RequestMetadataQueue> mRequestMetadataQueue;
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index f4b3197..ba97367 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -34,10 +34,11 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId, bool isMultiResolution) :
+ int setId, bool isMultiResolution, int dynamicRangeProfile) :
Camera3Stream(id, type,
width, height, maxSize, format, dataSpace, rotation,
- physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution),
+ physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
+ dynamicRangeProfile),
mTotalBufferCount(0),
mHandoutTotalBufferCount(0),
mHandoutOutputBufferCount(0),
@@ -87,6 +88,7 @@
if (strlen(camera_stream::physical_camera_id) > 0) {
lines.appendFormat(" Physical camera id: %s\n", camera_stream::physical_camera_id);
}
+ lines.appendFormat(" Dynamic Range Profile: 0x%x", camera_stream::dynamic_range_profile);
lines.appendFormat(" Frames produced: %d, last timestamp: %" PRId64 " ns\n",
mFrameCount, mLastTimestamp);
lines.appendFormat(" Total buffers: %zu, currently dequeued: %zu\n",
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index fb73c97..518ee42 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -37,7 +37,8 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
+ int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
+ int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
public:
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 0dfeac3..69723b6 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -46,10 +46,11 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId, bool isMultiResolution) :
+ int setId, bool isMultiResolution, int dynamicRangeProfile) :
Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
/*maxSize*/0, format, dataSpace, rotation,
- physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution),
+ physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
+ dynamicRangeProfile),
mConsumer(consumer),
mTransform(0),
mTraceFirstBuffer(true),
@@ -74,10 +75,10 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId, bool isMultiResolution) :
+ int setId, bool isMultiResolution, int dynamicRangeProfile) :
Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height, maxSize,
format, dataSpace, rotation, physicalCameraId, sensorPixelModesUsed,
- setId, isMultiResolution),
+ setId, isMultiResolution, dynamicRangeProfile),
mConsumer(consumer),
mTransform(0),
mTraceFirstBuffer(true),
@@ -109,10 +110,11 @@
camera_stream_rotation_t rotation, nsecs_t timestampOffset,
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId, bool isMultiResolution) :
+ int setId, bool isMultiResolution, int dynamicRangeProfile) :
Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
/*maxSize*/0, format, dataSpace, rotation,
- physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution),
+ physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
+ dynamicRangeProfile),
mConsumer(nullptr),
mTransform(0),
mTraceFirstBuffer(true),
@@ -149,11 +151,13 @@
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
uint64_t consumerUsage, nsecs_t timestampOffset,
- int setId, bool isMultiResolution) :
+ int setId, bool isMultiResolution,
+ int dynamicRangeProfile) :
Camera3IOStreamBase(id, type, width, height,
/*maxSize*/0,
format, dataSpace, rotation,
- physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution),
+ physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
+ dynamicRangeProfile),
mTransform(0),
mTraceFirstBuffer(true),
mUseMonoTimestamp(false),
@@ -379,6 +383,9 @@
__FUNCTION__, mId, strerror(-res), res);
return res;
}
+
+ queueHDRMetadata(anwBuffer->handle, currentConsumer, dynamic_range_profile);
+
res = queueBufferToConsumer(currentConsumer, anwBuffer, anwReleaseFence, surface_ids);
if (shouldLogError(res, state)) {
ALOGE("%s: Stream %d: Error queueing buffer to native window:"
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index a70b883..d9bf62a 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -89,7 +89,8 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
+ int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
+ int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
/**
* Set up a stream for formats that have a variable buffer size for the same
* dimensions, such as compressed JPEG.
@@ -101,7 +102,8 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
+ int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
+ int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
/**
* Set up a stream with deferred consumer for formats that have 2 dimensions, such as
* RAW and YUV. The consumer must be set before using this stream for output. A valid
@@ -112,7 +114,8 @@
camera_stream_rotation_t rotation, nsecs_t timestampOffset,
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
+ int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
+ int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
virtual ~Camera3OutputStream();
@@ -239,7 +242,8 @@
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
uint64_t consumerUsage = 0, nsecs_t timestampOffset = 0,
- int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
+ int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
+ int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
/**
* Note that we release the lock briefly in this function
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index 9e0c8f3..0e2671a 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -33,10 +33,10 @@
camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId, bool useHalBufManager) :
+ int setId, bool useHalBufManager, int dynamicProfile) :
Camera3OutputStream(id, CAMERA_STREAM_OUTPUT, width, height,
format, dataSpace, rotation, physicalCameraId, sensorPixelModesUsed,
- consumerUsage, timestampOffset, setId),
+ consumerUsage, timestampOffset, setId, dynamicProfile),
mUseHalBufManager(useHalBufManager) {
size_t consumerCount = std::min(surfaces.size(), kMaxOutputs);
if (surfaces.size() > consumerCount) {
@@ -67,7 +67,7 @@
}
res = mStreamSplitter->connect(initialSurfaces, usage, mUsage, camera_stream::max_buffers,
- getWidth(), getHeight(), getFormat(), &mConsumer);
+ getWidth(), getHeight(), getFormat(), &mConsumer, camera_stream::dynamic_range_profile);
if (res != OK) {
ALOGE("%s: Failed to connect to stream splitter: %s(%d)",
__FUNCTION__, strerror(-res), res);
@@ -388,13 +388,15 @@
bool sizeMismatch = ((static_cast<uint32_t>(infoIt.width) != getWidth()) ||
(static_cast<uint32_t> (infoIt.height) != getHeight())) ?
true : false;
- if ((imgReaderUsage && sizeMismatch) ||
+ bool dynamicRangeMismatch = dynamic_range_profile != infoIt.dynamicRangeProfile;
+ if ((imgReaderUsage && sizeMismatch) || dynamicRangeMismatch ||
(infoIt.format != getOriginalFormat() && infoIt.format != getFormat()) ||
(infoIt.dataSpace != getDataSpace() &&
infoIt.dataSpace != getOriginalDataSpace())) {
- ALOGE("%s: Shared surface parameters format: 0x%x dataSpace: 0x%x "
- " don't match source stream format: 0x%x dataSpace: 0x%x", __FUNCTION__,
- infoIt.format, infoIt.dataSpace, getFormat(), getDataSpace());
+ ALOGE("%s: Shared surface parameters format: 0x%x dataSpace: 0x%x dynamic range 0x%x "
+ " don't match source stream format: 0x%x dataSpace: 0x%x dynamic range 0x%x"
+ , __FUNCTION__, infoIt.format, infoIt.dataSpace, infoIt.dynamicRangeProfile,
+ getFormat(), getDataSpace(), dynamic_range_profile);
return BAD_VALUE;
}
}
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index 4b6341b..fafa26f 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -40,7 +40,8 @@
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
int setId = CAMERA3_STREAM_SET_ID_INVALID,
- bool useHalBufManager = false);
+ bool useHalBufManager = false,
+ int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
virtual ~Camera3SharedOutputStream();
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 1405fa1..83f9a98 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <vector>
+#include "system/window.h"
#define LOG_TAG "Camera3-Stream"
#define ATRACE_TAG ATRACE_TAG_CAMERA
//#define LOG_NDEBUG 0
@@ -23,6 +25,7 @@
#include "device3/Camera3Stream.h"
#include "device3/StatusTracker.h"
#include "utils/TraceHFR.h"
+#include "ui/GraphicBufferMapper.h"
#include <cutils/properties.h>
@@ -51,7 +54,7 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId, bool isMultiResolution) :
+ int setId, bool isMultiResolution, int dynamicRangeProfile) :
camera_stream(),
mId(id),
mSetId(setId),
@@ -87,6 +90,7 @@
camera_stream::max_buffers = 0;
camera_stream::physical_camera_id = mPhysicalCameraId.string();
camera_stream::sensor_pixel_modes_used = sensorPixelModesUsed;
+ camera_stream::dynamic_range_profile = dynamicRangeProfile;
if ((format == HAL_PIXEL_FORMAT_BLOB || format == HAL_PIXEL_FORMAT_RAW_OPAQUE) &&
maxSize == 0) {
@@ -147,6 +151,10 @@
return mOriginalFormat;
}
+int Camera3Stream::getDynamicRangeProfile() const {
+ return camera_stream::dynamic_range_profile;
+}
+
void Camera3Stream::setDataSpaceOverride(bool dataSpaceOverridden) {
mDataSpaceOverridden = dataSpaceOverridden;
}
@@ -1078,6 +1086,52 @@
return res;
}
+void Camera3Stream::queueHDRMetadata(buffer_handle_t buffer, sp<ANativeWindow>& anw,
+ int dynamicRangeProfile) {
+ auto& mapper = GraphicBufferMapper::get();
+ switch (dynamicRangeProfile) {
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10: {
+ std::optional<ui::Smpte2086> smpte2086;
+ auto res = mapper.getSmpte2086(buffer, &smpte2086);
+ if ((res == OK) && smpte2086.has_value()) {
+ const auto& metaValue = smpte2086.value();
+ android_smpte2086_metadata meta = {
+ .displayPrimaryRed.x = metaValue.primaryRed.x,
+ .displayPrimaryRed.y = metaValue.primaryRed.y,
+ .displayPrimaryGreen.x = metaValue.primaryGreen.x,
+ .displayPrimaryGreen.y = metaValue.primaryGreen.y,
+ .displayPrimaryBlue.x = metaValue.primaryBlue.x,
+ .displayPrimaryBlue.y = metaValue.primaryBlue.y,
+ .whitePoint.x = metaValue.whitePoint.x,
+ .whitePoint.y = metaValue.whitePoint.y,
+ .maxLuminance = metaValue.maxLuminance,
+ .minLuminance = metaValue.minLuminance};
+ native_window_set_buffers_smpte2086_metadata(anw.get(), &meta);
+ } else {
+ ALOGE("%s Couldn't retrieve Smpte2086 metadata %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ }
+ break;
+ }
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS: {
+ std::optional<std::vector<uint8_t>> smpte2094_40;
+ auto res = mapper.getSmpte2094_40(buffer, &smpte2094_40);
+ if ((res == OK) && smpte2094_40.has_value()) {
+ native_window_set_buffers_hdr10_plus_metadata(anw.get(),
+ smpte2094_40.value().size(), smpte2094_40.value().data());
+ } else {
+ ALOGE("%s Couldn't retrieve Smpte2094_40 metadata %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ }
+ break;
+ }
+ default:
+ // No-op
+ break;
+ }
+}
+
+
}; // namespace camera3
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 17041de..bbbea8d 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -138,6 +138,10 @@
static Camera3Stream* cast(camera_stream *stream);
static const Camera3Stream* cast(const camera_stream *stream);
+ // Queue corresponding HDR metadata to given native window.
+ static void queueHDRMetadata(buffer_handle_t buffer, sp<ANativeWindow>& anw,
+ int dynamicRangeProfile);
+
/**
* Get the stream's ID
*/
@@ -168,6 +172,7 @@
void setFormatOverride(bool formatOverriden);
bool isFormatOverridden() const;
int getOriginalFormat() const;
+ int getDynamicRangeProfile() const;
void setDataSpaceOverride(bool dataSpaceOverriden);
bool isDataSpaceOverridden() const;
android_dataspace getOriginalDataSpace() const;
@@ -500,7 +505,7 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId, bool isMultiResolution);
+ int setId, bool isMultiResolution, int dynamicRangeProfile);
wp<Camera3StreamBufferFreedListener> mBufferFreedListener;
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index 5f20f17..ef10f0d 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -64,6 +64,7 @@
const char* physical_camera_id;
std::unordered_set<int32_t> sensor_pixel_modes_used;
+ int dynamic_range_profile;
} camera_stream_t;
typedef struct camera_stream_buffer {
@@ -107,14 +108,17 @@
bool finalized = false;
bool supportsOffline = false;
std::unordered_set<int32_t> sensorPixelModesUsed;
+ int dynamicRangeProfile;
OutputStreamInfo() :
width(-1), height(-1), format(-1), dataSpace(HAL_DATASPACE_UNKNOWN),
- consumerUsage(0) {}
+ consumerUsage(0),
+ dynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) {}
OutputStreamInfo(int _width, int _height, int _format, android_dataspace _dataSpace,
- uint64_t _consumerUsage, const std::unordered_set<int32_t>& _sensorPixelModesUsed) :
+ uint64_t _consumerUsage, const std::unordered_set<int32_t>& _sensorPixelModesUsed,
+ int _dynamicRangeProfile) :
width(_width), height(_height), format(_format),
dataSpace(_dataSpace), consumerUsage(_consumerUsage),
- sensorPixelModesUsed(_sensorPixelModesUsed) {}
+ sensorPixelModesUsed(_sensorPixelModesUsed), dynamicRangeProfile(_dynamicRangeProfile){}
};
/**
@@ -154,6 +158,7 @@
virtual uint32_t getWidth() const = 0;
virtual uint32_t getHeight() const = 0;
virtual int getFormat() const = 0;
+ virtual int getDynamicRangeProfile() const = 0;
virtual android_dataspace getDataSpace() const = 0;
virtual void setFormatOverride(bool formatOverriden) = 0;
virtual bool isFormatOverridden() const = 0;
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
index 5c6c518..1149d13 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
@@ -34,13 +34,16 @@
#include <cutils/atomic.h>
+#include "Camera3Stream.h"
+
#include "Camera3StreamSplitter.h"
namespace android {
status_t Camera3StreamSplitter::connect(const std::unordered_map<size_t, sp<Surface>> &surfaces,
uint64_t consumerUsage, uint64_t producerUsage, size_t halMaxBuffers, uint32_t width,
- uint32_t height, android::PixelFormat format, sp<Surface>* consumer) {
+ uint32_t height, android::PixelFormat format, sp<Surface>* consumer,
+ int dynamicRangeProfile) {
ATRACE_CALL();
if (consumer == nullptr) {
SP_LOGE("%s: consumer pointer is NULL", __FUNCTION__);
@@ -61,6 +64,7 @@
mMaxHalBuffers = halMaxBuffers;
mConsumerName = getUniqueConsumerName();
+ mDynamicRangeProfile = dynamicRangeProfile;
// Add output surfaces. This has to be before creating internal buffer queue
// in order to get max consumer side buffers.
for (auto &it : surfaces) {
@@ -136,6 +140,7 @@
}
}
mOutputs.clear();
+ mOutputSurfaces.clear();
mOutputSlots.clear();
mConsumerBufferCount.clear();
@@ -258,6 +263,7 @@
// Add new entry into mOutputs
mOutputs[surfaceId] = gbp;
+ mOutputSurfaces[surfaceId] = outputQueue;
mConsumerBufferCount[surfaceId] = maxConsumerBuffers;
if (mConsumerBufferCount[surfaceId] > mMaxHalBuffers) {
SP_LOGW("%s: Consumer buffer count %zu larger than max. Hal buffers: %zu", __FUNCTION__,
@@ -316,6 +322,7 @@
}
}
mOutputs[surfaceId] = nullptr;
+ mOutputSurfaces[surfaceId] = nullptr;
mOutputSlots[gbp] = nullptr;
for (const auto &id : pendingBufferIds) {
decrementBufRefCountLocked(id, surfaceId);
@@ -356,6 +363,14 @@
const BufferTracker& tracker = *(mBuffers[bufferId]);
int slot = getSlotForOutputLocked(output, tracker.getBuffer());
+ if (mOutputSurfaces[surfaceId] != nullptr) {
+ sp<ANativeWindow> anw = mOutputSurfaces[surfaceId];
+ camera3::Camera3Stream::queueHDRMetadata(
+ bufferItem.mGraphicBuffer->getNativeBuffer()->handle, anw, mDynamicRangeProfile);
+ } else {
+ SP_LOGE("%s: Invalid surface id: %zu!", __FUNCTION__, surfaceId);
+ }
+
// In case the output BufferQueue has its own lock, if we hold splitter lock while calling
// queueBuffer (which will try to acquire the output lock), the output could be holding its
// own lock calling releaseBuffer (which will try to acquire the splitter lock), running into
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
index 4eb455a..827865c 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
@@ -19,6 +19,8 @@
#include <unordered_set>
+#include <camera/CameraMetadata.h>
+
#include <gui/IConsumerListener.h>
#include <gui/IProducerListener.h>
#include <gui/BufferItemConsumer.h>
@@ -55,7 +57,8 @@
// with output surfaces.
status_t connect(const std::unordered_map<size_t, sp<Surface>> &surfaces,
uint64_t consumerUsage, uint64_t producerUsage, size_t halMaxBuffers, uint32_t width,
- uint32_t height, android::PixelFormat format, sp<Surface>* consumer);
+ uint32_t height, android::PixelFormat format, sp<Surface>* consumer,
+ int dynamicRangeProfile);
// addOutput adds an output BufferQueue to the splitter. The splitter
// connects to outputQueue as a CPU producer, and any buffers queued
@@ -232,6 +235,7 @@
uint32_t mHeight = 0;
android::PixelFormat mFormat = android::PIXEL_FORMAT_NONE;
uint64_t mProducerUsage = 0;
+ int mDynamicRangeProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
// The attachBuffer call will happen on different thread according to mUseHalBufManager and have
// different timing constraint.
@@ -251,6 +255,9 @@
//Map surface ids -> gbp outputs
std::unordered_map<int, sp<IGraphicBufferProducer> > mOutputs;
+ //Map surface ids -> gbp outputs
+ std::unordered_map<int, sp<Surface>> mOutputSurfaces;
+
//Map surface ids -> consumer buffer count
std::unordered_map<int, size_t > mConsumerBufferCount;
diff --git a/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp b/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp
index b64ec0d..6135f9e 100644
--- a/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp
+++ b/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp
@@ -196,6 +196,9 @@
return res;
}
+ Camera3Stream::queueHDRMetadata(bufferHolder.anwBuffer.get()->handle, mConsumer,
+ mParent.getDynamicRangeProfile());
+
res = mConsumer->queueBuffer(mConsumer.get(), bufferHolder.anwBuffer.get(),
bufferHolder.releaseFence);
if (res != OK) {