Camera: pass bufferId to HIDL interface
This gives each buffer a unique ID and save some time sending
buffer_handle_t to HAL process.
Bug: 30985004
Change-Id: Idf0d3edde94e1331cadb271dce3e4bed8bfb8c14
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 6f64dc3..68fe8c9 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -3113,7 +3113,7 @@
res = mHal3Device->ops->configure_streams(mHal3Device, config);
} else {
// Convert stream config to HIDL
-
+ std::set<int> activeStreams;
StreamConfiguration requestedConfiguration;
requestedConfiguration.streams.resize(config->num_streams);
for (size_t i = 0; i < config->num_streams; i++) {
@@ -3142,7 +3142,24 @@
dst.usage = mapToConsumerUsage(src->usage);
dst.dataSpace = mapToHidlDataspace(src->data_space);
dst.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
+
+ activeStreams.insert(streamId);
+ // Create Buffer ID map if necessary
+ if (mBufferIdMaps.count(streamId) == 0) {
+ mBufferIdMaps.emplace(streamId, BufferIdMap{});
+ }
}
+ // remove BufferIdMap for deleted streams
+ for(auto it = mBufferIdMaps.begin(); it != mBufferIdMaps.end();) {
+ int streamId = it->first;
+ bool active = activeStreams.count(streamId) > 0;
+ if (!active) {
+ it = mBufferIdMaps.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
requestedConfiguration.operationMode = mapToStreamConfigurationMode(
(camera3_stream_configuration_mode_t) config->operation_mode);
@@ -3239,8 +3256,13 @@
std::lock_guard<std::mutex> lock(mInflightLock);
if (request->input_buffer != nullptr) {
int32_t streamId = Camera3Stream::cast(request->input_buffer->stream)->getId();
+ buffer_handle_t buf = *(request->input_buffer->buffer);
+ auto pair = getBufferId(buf, streamId);
+ bool isNewBuffer = pair.first;
+ uint64_t bufferId = pair.second;
captureRequest.inputBuffer.streamId = streamId;
- captureRequest.inputBuffer.buffer = *(request->input_buffer->buffer);
+ captureRequest.inputBuffer.bufferId = bufferId;
+ captureRequest.inputBuffer.buffer = (isNewBuffer) ? buf : nullptr;
captureRequest.inputBuffer.status = BufferStatus::OK;
native_handle_t *acquireFence = nullptr;
if (request->input_buffer->acquire_fence != -1) {
@@ -3253,6 +3275,9 @@
pushInflightBufferLocked(captureRequest.frameNumber, streamId,
request->input_buffer->buffer);
+ } else {
+ captureRequest.inputBuffer.streamId = -1;
+ captureRequest.inputBuffer.bufferId = BUFFER_ID_NO_BUFFER;
}
captureRequest.outputBuffers.resize(request->num_output_buffers);
@@ -3260,8 +3285,12 @@
const camera3_stream_buffer_t *src = request->output_buffers + i;
StreamBuffer &dst = captureRequest.outputBuffers[i];
int32_t streamId = Camera3Stream::cast(src->stream)->getId();
+ buffer_handle_t buf = *(src->buffer);
+ auto pair = getBufferId(buf, streamId);
+ bool isNewBuffer = pair.first;
dst.streamId = streamId;
- dst.buffer = *(src->buffer);
+ dst.bufferId = pair.second;
+ dst.buffer = isNewBuffer ? buf : nullptr;
dst.status = BufferStatus::OK;
native_handle_t *acquireFence = nullptr;
if (src->acquire_fence != -1) {
@@ -3344,6 +3373,20 @@
return OK;
}
+std::pair<bool, uint64_t> Camera3Device::HalInterface::getBufferId(
+ const buffer_handle_t& buf, int streamId) {
+ std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+
+ BufferIdMap& bIdMap = mBufferIdMaps.at(streamId);
+ auto it = bIdMap.find(buf);
+ if (it == bIdMap.end()) {
+ bIdMap[buf] = mNextBufferId++;
+ return std::make_pair(true, mNextBufferId - 1);
+ } else {
+ return std::make_pair(false, it->second);
+ }
+}
+
/**
* RequestThread inner class methods
*/
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 217c8b7..014721a 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -257,6 +257,53 @@
buffer_handle_t *buffer);
// Cache of buffer handles keyed off (frameNumber << 32 | streamId)
std::unordered_map<uint64_t, buffer_handle_t*> mInflightBufferMap;
+
+ struct BufferHasher {
+ size_t operator()(const buffer_handle_t& buf) const {
+ if (buf == nullptr)
+ return 0;
+
+ size_t result = 1;
+ result = 31 * result + buf->numFds;
+ result = 31 * result + buf->numInts;
+ int length = buf->numFds + buf->numInts;
+ for (int i = 0; i < length; i++) {
+ result = 31 * result + buf->data[i];
+ }
+ return result;
+ }
+ };
+
+ struct BufferComparator {
+ bool operator()(const buffer_handle_t& buf1, const buffer_handle_t& buf2) const {
+ if (buf1->numFds == buf2->numFds && buf1->numInts == buf2->numInts) {
+ int length = buf1->numFds + buf1->numInts;
+ for (int i = 0; i < length; i++) {
+ if (buf1->data[i] != buf2->data[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+ };
+
+ std::mutex mBufferIdMapLock; // protecting mBufferIdMaps and mNextBufferId
+ typedef std::unordered_map<const buffer_handle_t, uint64_t,
+ BufferHasher, BufferComparator> BufferIdMap;
+ // stream ID -> per stream buffer ID map
+ std::unordered_map<int, BufferIdMap> mBufferIdMaps;
+ uint64_t mNextBufferId = 1; // 0 means no buffer
+ static const uint64_t BUFFER_ID_NO_BUFFER = 0;
+
+ // method to extract buffer's unique ID
+ // TODO: we should switch to use gralloc mapper's getBackingStore API
+ // once we ran in binderized gralloc mode, but before that is ready,
+ // we need to rely on the conventional buffer queue behavior where
+ // buffer_handle_t's FD won't change.
+ // return pair of (newlySeenBuffer?, bufferId)
+ std::pair<bool, uint64_t> getBufferId(const buffer_handle_t& buf, int streamId);
};
std::unique_ptr<HalInterface> mInterface;