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

Commit 9cdd6f95 authored by Yuriy Romanenko's avatar Yuriy Romanenko Committed by Yin-Chia Yeh
Browse files

External: Switch to legacy V4L2 buffer mapping

Required for older kernels like 3.x

Change-Id: I0680320b606727bdb0b22dab1df8c5954d623f10
parent fe1192ec
Loading
Loading
Loading
Loading
+18 −17
Original line number Diff line number Diff line
@@ -611,7 +611,12 @@ void ExternalCameraDeviceSession::invokeProcessCaptureResultCallback(
            }
        }
    }
    mCallback->processCaptureResult(results);
    auto status = mCallback->processCaptureResult(results);
    if (!status.isOk()) {
        ALOGE("%s: processCaptureResult ERROR : %s", __FUNCTION__,
              status.description().c_str());
    }

    mProcessCaptureResultLock.unlock();
}

@@ -1835,7 +1840,7 @@ int ExternalCameraDeviceSession::v4l2StreamOffLocked() {
            return -1;
        }
    }
    mV4l2Buffers.clear(); // VIDIOC_REQBUFS will fail if FDs are not clear first
    mV4L2BufferCount = 0;

    // VIDIOC_STREAMOFF
    v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -1955,24 +1960,20 @@ int ExternalCameraDeviceSession::configureV4l2StreamLocked(const SupportedV4L2Fo
        return NO_MEMORY;
    }

    // VIDIOC_EXPBUF:  export buffers as FD
    // VIDIOC_QUERYBUF:  get buffer offset in the V4L2 fd
    // VIDIOC_QBUF: send buffer to driver
    mV4l2Buffers.resize(req_buffers.count);
    mV4L2BufferCount = req_buffers.count;
    for (uint32_t i = 0; i < req_buffers.count; i++) {
        v4l2_exportbuffer expbuf {};
        expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        expbuf.index = i;
        if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_EXPBUF, &expbuf)) < 0) {
            ALOGE("%s: EXPBUF %d failed: %s", __FUNCTION__, i,  strerror(errno));
            return -errno;
        }
        mV4l2Buffers[i].reset(expbuf.fd);

        v4l2_buffer buffer = {
            .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
            .index = i,
            .memory = V4L2_MEMORY_MMAP};

        if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QUERYBUF, &buffer)) < 0) {
            ALOGE("%s: QUERYBUF %d failed: %s", __FUNCTION__, i,  strerror(errno));
            return -errno;
        }

        if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer)) < 0) {
            ALOGE("%s: QBUF %d failed: %s", __FUNCTION__, i,  strerror(errno));
            return -errno;
@@ -2012,7 +2013,7 @@ sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked() {

    {
        std::unique_lock<std::mutex> lk(mV4l2BufferLock);
        if (mNumDequeuedV4l2Buffers == mV4l2Buffers.size()) {
        if (mNumDequeuedV4l2Buffers == mV4L2BufferCount) {
            std::chrono::seconds timeout = std::chrono::seconds(kBufferWaitTimeoutSec);
            mLock.unlock();
            auto st = mV4L2BufferReturned.wait_for(lk, timeout);
@@ -2032,7 +2033,7 @@ sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked() {
        return ret;
    }

    if (buffer.index >= mV4l2Buffers.size()) {
    if (buffer.index >= mV4L2BufferCount) {
        ALOGE("%s: Invalid buffer id: %d", __FUNCTION__, buffer.index);
        return ret;
    }
@@ -2048,7 +2049,7 @@ sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked() {
    }
    return new V4L2Frame(
            mV4l2StreamingFmt.width, mV4l2StreamingFmt.height, mV4l2StreamingFmt.fourcc,
            buffer.index, mV4l2Buffers[buffer.index].get(), buffer.bytesused);
            buffer.index, mV4l2Fd.get(), buffer.bytesused, buffer.m.offset);
}

void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp<V4L2Frame>& frame) {
@@ -2243,7 +2244,7 @@ Status ExternalCameraDeviceSession::configureStreams(
                BufferUsage::CPU_WRITE_OFTEN |
                BufferUsage::CAMERA_OUTPUT;
        out->streams[i].v3_2.consumerUsage = 0;
        out->streams[i].v3_2.maxBuffers  = mV4l2Buffers.size();
        out->streams[i].v3_2.maxBuffers  = mV4L2BufferCount;

        switch (config.streams[i].format) {
            case PixelFormat::BLOB:
+3 −3
Original line number Diff line number Diff line
@@ -40,9 +40,9 @@ const char* ExternalCameraDeviceConfig::kDefaultCfgPath = "/vendor/etc/external_

V4L2Frame::V4L2Frame(
        uint32_t w, uint32_t h, uint32_t fourcc,
        int bufIdx, int fd, uint32_t dataSize) :
        int bufIdx, int fd, uint32_t dataSize, uint64_t offset) :
        mWidth(w), mHeight(h), mFourcc(fourcc),
        mBufferIndex(bufIdx), mFd(fd), mDataSize(dataSize) {}
        mBufferIndex(bufIdx), mFd(fd), mDataSize(dataSize), mOffset(offset) {}

int V4L2Frame::map(uint8_t** data, size_t* dataSize) {
    if (data == nullptr || dataSize == nullptr) {
@@ -53,7 +53,7 @@ int V4L2Frame::map(uint8_t** data, size_t* dataSize) {

    std::lock_guard<std::mutex> lk(mLock);
    if (!mMapped) {
        void* addr = mmap(NULL, mDataSize, PROT_READ, MAP_SHARED, mFd, 0);
        void* addr = mmap(NULL, mDataSize, PROT_READ, MAP_SHARED, mFd, mOffset);
        if (addr == MAP_FAILED) {
            ALOGE("%s: V4L2 buffer map failed: %s", __FUNCTION__, strerror(errno));
            return -EINVAL;
+1 −1
Original line number Diff line number Diff line
@@ -293,7 +293,7 @@ protected:

    bool mV4l2Streaming = false;
    SupportedV4L2Format mV4l2StreamingFmt;
    std::vector<unique_fd> mV4l2Buffers;
    size_t mV4L2BufferCount;

    static const int kBufferWaitTimeoutSec = 3; // TODO: handle long exposure (or not allowing)
    std::mutex mV4l2BufferLock; // protect the buffer count and condition below
+3 −1
Original line number Diff line number Diff line
@@ -45,7 +45,8 @@ struct SupportedV4L2Format {
// Also contains necessary information to enqueue the buffer back to V4L2 buffer queue
class V4L2Frame : public virtual VirtualLightRefBase {
public:
    V4L2Frame(uint32_t w, uint32_t h, uint32_t fourcc, int bufIdx, int fd, uint32_t dataSize);
    V4L2Frame(uint32_t w, uint32_t h, uint32_t fourcc, int bufIdx, int fd,
              uint32_t dataSize, uint64_t offset);
    ~V4L2Frame() override;
    const uint32_t mWidth;
    const uint32_t mHeight;
@@ -57,6 +58,7 @@ private:
    std::mutex mLock;
    const int mFd; // used for mmap but doesn't claim ownership
    const size_t mDataSize;
    const uint64_t mOffset; // used for mmap
    uint8_t* mData = nullptr;
    bool  mMapped = false;
};