Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 77327052 authored by Yin-Chia Yeh's avatar Yin-Chia Yeh
Browse files

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
parent e396e1cf
Loading
Loading
Loading
Loading
+46 −3
Original line number Diff line number Diff line
@@ -3113,7 +3113,7 @@ status_t Camera3Device::HalInterface::configureStreams(camera3_stream_configurat
        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 @@ status_t Camera3Device::HalInterface::configureStreams(camera3_stream_configurat
            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 @@ status_t Camera3Device::HalInterface::processCaptureRequest(
            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 @@ status_t Camera3Device::HalInterface::processCaptureRequest(

                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 @@ status_t Camera3Device::HalInterface::processCaptureRequest(
                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 @@ status_t Camera3Device::HalInterface::popInflightBuffer(
    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
 */
+47 −0
Original line number Diff line number Diff line
@@ -257,6 +257,53 @@ class Camera3Device :
                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;