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

Commit 70c35c39 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "ExternalCameraHAL: Get old image if taking picture without preview" into main

parents 8c8c1c12 8c428d7a
Loading
Loading
Loading
Loading
+61 −29
Original line number Diff line number Diff line
@@ -1136,6 +1136,11 @@ int ExternalCameraDeviceSession::configureV4l2StreamLocked(const SupportedV4L2Fo

    uint32_t v4lBufferCount = (fps >= kDefaultFps) ? mCfg.numVideoBuffers : mCfg.numStillBuffers;

    // Double the max lag in theory.
    mMaxLagNs = v4lBufferCount * 1000000000LL * 2 / fps;
    ALOGI("%s: set mMaxLagNs to %" PRIu64 " ns, v4lBufferCount %u", __FUNCTION__, mMaxLagNs,
          v4lBufferCount);

    // VIDIOC_REQBUFS: create buffers
    v4l2_requestbuffers req_buffers{};
    req_buffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -1232,8 +1237,10 @@ std::unique_ptr<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked(n
        }
    }

    ATRACE_BEGIN("VIDIOC_DQBUF");
    uint64_t lagNs = 0;
    v4l2_buffer buffer{};
    do {
        ATRACE_BEGIN("VIDIOC_DQBUF");
        buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buffer.memory = V4L2_MEMORY_MMAP;
        if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_DQBUF, &buffer)) < 0) {
@@ -1258,14 +1265,39 @@ std::unique_ptr<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked(n
            return ret;
        }

        nsecs_t curTimeNs = systemTime(SYSTEM_TIME_MONOTONIC);

        if (buffer.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) {
            // Ideally we should also check for V4L2_BUF_FLAG_TSTAMP_SRC_SOE, but
            // even V4L2_BUF_FLAG_TSTAMP_SRC_EOF is better than capture a timestamp now
            *shutterTs = static_cast<nsecs_t>(buffer.timestamp.tv_sec) * 1000000000LL +
                         buffer.timestamp.tv_usec * 1000LL;
        } else {
        *shutterTs = systemTime(SYSTEM_TIME_MONOTONIC);
            *shutterTs = curTimeNs;
        }

        // The tactic only takes effect on v4l2 buffers with flag V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC.
        // Most USB cameras should have the feature.
        if (curTimeNs < *shutterTs) {
            lagNs = 0;
            ALOGW("%s: should not happen, the monotonic clock has issue, shutterTs is in the "
                  "future, curTimeNs %" PRId64 "  < "
                  "shutterTs %" PRId64 "",
                  __func__, curTimeNs, *shutterTs);
        } else {
            lagNs = curTimeNs - *shutterTs;
        }

        if (lagNs > mMaxLagNs) {
            ALOGI("%s: drop too old buffer, index %d, lag %" PRIu64 " ns > max %" PRIu64 " ns", __FUNCTION__,
                  buffer.index, lagNs, mMaxLagNs);
            int retVal = ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer);
            if (retVal) {
                ALOGE("%s: unexpected VIDIOC_QBUF failed, retVal %d", __FUNCTION__, retVal);
                return ret;
            }
        }
    } while (lagNs > mMaxLagNs);

    {
        std::lock_guard<std::mutex> lk(mV4l2BufferLock);
+3 −0
Original line number Diff line number Diff line
@@ -382,6 +382,9 @@ class ExternalCameraDeviceSession : public BnCameraDeviceSession, public OutputT
    std::string mExifMake;
    std::string mExifModel;
    /* End of members not changed after initialize() */

    // The max tolerant lag between the dequeued v4l2 buffer and current capture request.
    uint64_t mMaxLagNs;
};

}  // namespace implementation