Loading services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -89,9 +89,10 @@ void Camera3IOStreamBase::dump(int fd, const Vector<String16> &args) const { 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%" PRIx64, lines.appendFormat(" Dynamic Range Profile: 0x%" PRIx64 "\n", camera_stream::dynamic_range_profile); lines.appendFormat(" Stream use case: %" PRId64 "\n", camera_stream::use_case); lines.appendFormat(" Timestamp base: %d\n", getTimestampBase()); lines.appendFormat(" Frames produced: %d, last timestamp: %" PRId64 " ns\n", mFrameCount, mLastTimestamp); lines.appendFormat(" Total buffers: %zu, currently dequeued: %zu\n", Loading services/camera/libcameraservice/device3/Camera3OutputStream.cpp +21 −5 Original line number Diff line number Diff line Loading @@ -466,8 +466,10 @@ status_t Camera3OutputStream::returnBufferCheckedLocked( nsecs_t captureTime = (mUseReadoutTime && readoutTimestamp != 0 ? readoutTimestamp : timestamp) - mTimestampOffset; if (mPreviewFrameSpacer != nullptr) { res = mPreviewFrameSpacer->queuePreviewBuffer(captureTime, transform, anwBuffer, anwReleaseFence); nsecs_t readoutTime = (readoutTimestamp != 0 ? readoutTimestamp : timestamp) - mTimestampOffset; res = mPreviewFrameSpacer->queuePreviewBuffer(captureTime, readoutTime, transform, anwBuffer, anwReleaseFence); if (res != OK) { ALOGE("%s: Stream %d: Error queuing buffer to preview buffer spacer: %s (%d)", __FUNCTION__, mId, strerror(-res), res); Loading Loading @@ -684,12 +686,15 @@ status_t Camera3OutputStream::configureConsumerQueueLocked(bool allowPreviewResp bool forceChoreographer = (timestampBase == OutputConfiguration::TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED); bool defaultToChoreographer = (isDefaultTimeBase && isConsumedByHWComposer() && !property_get_bool("camera.disable_preview_scheduler", false)); isConsumedByHWComposer()); bool defaultToSpacer = (isDefaultTimeBase && isConsumedByHWTexture() && !isConsumedByCPU() && !isVideoStream()); if (forceChoreographer || defaultToChoreographer) { mSyncToDisplay = true; mTotalBufferCount += kDisplaySyncExtraBuffer; } else if (isConsumedByHWTexture() && !isVideoStream()) { } else if (defaultToSpacer) { mPreviewFrameSpacer = new PreviewFrameSpacer(*this, mConsumer); mTotalBufferCount ++; res = mPreviewFrameSpacer->run(String8::format("PreviewSpacer-%d", mId).string()); Loading Loading @@ -1268,6 +1273,17 @@ bool Camera3OutputStream::isConsumedByHWTexture() const { return (usage & GRALLOC_USAGE_HW_TEXTURE) != 0; } bool Camera3OutputStream::isConsumedByCPU() const { uint64_t usage = 0; status_t res = getEndpointUsage(&usage); if (res != OK) { ALOGE("%s: getting end point usage failed: %s (%d).", __FUNCTION__, strerror(-res), res); return false; } return (usage & GRALLOC_USAGE_SW_READ_MASK) != 0; } void Camera3OutputStream::dumpImageToDisk(nsecs_t timestamp, ANativeWindowBuffer* anwBuffer, int fence) { // Deriver output file name Loading services/camera/libcameraservice/device3/Camera3OutputStream.h +5 −0 Original line number Diff line number Diff line Loading @@ -159,6 +159,11 @@ class Camera3OutputStream : */ bool isConsumedByHWTexture() const; /** * Return if this output stream is consumed by CPU. */ bool isConsumedByCPU() const; /** * Return if the consumer configuration of this stream is deferred. */ Loading services/camera/libcameraservice/device3/PreviewFrameSpacer.cpp +13 −13 Original line number Diff line number Diff line Loading @@ -36,12 +36,12 @@ PreviewFrameSpacer::~PreviewFrameSpacer() { Thread::requestExitAndWait(); } status_t PreviewFrameSpacer::queuePreviewBuffer(nsecs_t timestamp, int32_t transform, ANativeWindowBuffer* anwBuffer, int releaseFence) { status_t PreviewFrameSpacer::queuePreviewBuffer(nsecs_t timestamp, nsecs_t readoutTimestamp, int32_t transform, ANativeWindowBuffer* anwBuffer, int releaseFence) { Mutex::Autolock l(mLock); mPendingBuffers.emplace(timestamp, transform, anwBuffer, releaseFence); ALOGV("%s: mPendingBuffers size %zu, timestamp %" PRId64, __FUNCTION__, mPendingBuffers.size(), timestamp); mPendingBuffers.emplace(timestamp, readoutTimestamp, transform, anwBuffer, releaseFence); ALOGV("%s: mPendingBuffers size %zu, timestamp %" PRId64 ", readoutTime %" PRId64, __FUNCTION__, mPendingBuffers.size(), timestamp, readoutTimestamp); mBufferCond.signal(); return OK; Loading @@ -56,17 +56,17 @@ bool PreviewFrameSpacer::threadLoop() { nsecs_t currentTime = systemTime(); auto buffer = mPendingBuffers.front(); nsecs_t captureInterval = buffer.timestamp - mLastCameraCaptureTime; // If the capture interval exceeds threshold, directly queue nsecs_t readoutInterval = buffer.readoutTimestamp - mLastCameraReadoutTime; // If the readout interval exceeds threshold, directly queue // cached buffer. if (captureInterval >= kFrameIntervalThreshold) { if (readoutInterval >= kFrameIntervalThreshold) { mPendingBuffers.pop(); queueBufferToClientLocked(buffer, currentTime); return true; } // Cache the frame to match capture time interval, for up to 33ms nsecs_t expectedQueueTime = mLastCameraPresentTime + captureInterval; // Cache the frame to match readout time interval, for up to 33ms nsecs_t expectedQueueTime = mLastCameraPresentTime + readoutInterval; nsecs_t frameWaitTime = std::min(kMaxFrameWaitTime, expectedQueueTime - currentTime); if (frameWaitTime > 0 && mPendingBuffers.size() < 2) { mBufferCond.waitRelative(mLock, frameWaitTime); Loading @@ -75,8 +75,8 @@ bool PreviewFrameSpacer::threadLoop() { } currentTime = systemTime(); } ALOGV("%s: captureInterval %" PRId64 ", queueInterval %" PRId64 ", waited for %" PRId64 ", timestamp %" PRId64, __FUNCTION__, captureInterval, ALOGV("%s: readoutInterval %" PRId64 ", queueInterval %" PRId64 ", waited for %" PRId64 ", timestamp %" PRId64, __FUNCTION__, readoutInterval, currentTime - mLastCameraPresentTime, frameWaitTime, buffer.timestamp); mPendingBuffers.pop(); queueBufferToClientLocked(buffer, currentTime); Loading Loading @@ -114,7 +114,7 @@ void PreviewFrameSpacer::queueBufferToClientLocked( } mLastCameraPresentTime = currentTime; mLastCameraCaptureTime = bufferHolder.timestamp; mLastCameraReadoutTime = bufferHolder.readoutTimestamp; } }; // namespace camera3 Loading services/camera/libcameraservice/device3/PreviewFrameSpacer.h +9 −7 Original line number Diff line number Diff line Loading @@ -42,8 +42,8 @@ class Camera3OutputStream; * * The PreviewFrameSpacer improves the viewfinder user experience by: * - Cache the frame buffers if the intervals between queueBuffer is shorter * than the camera capture intervals. * - Queue frame buffers in the same cadence as the camera capture time. * than the camera readout intervals. * - Queue frame buffers in the same cadence as the camera readout time. * - Maintain at most 1 queue-able buffer. If the 2nd preview buffer becomes * available, queue the oldest cached buffer to the buffer queue. */ Loading @@ -53,8 +53,8 @@ class PreviewFrameSpacer : public Thread { virtual ~PreviewFrameSpacer(); // Queue preview buffer locally status_t queuePreviewBuffer(nsecs_t timestamp, int32_t transform, ANativeWindowBuffer* anwBuffer, int releaseFence); status_t queuePreviewBuffer(nsecs_t timestamp, nsecs_t readoutTimestamp, int32_t transform, ANativeWindowBuffer* anwBuffer, int releaseFence); bool threadLoop() override; void requestExit() override; Loading @@ -63,12 +63,14 @@ class PreviewFrameSpacer : public Thread { // structure holding cached preview buffer info struct BufferHolder { nsecs_t timestamp; nsecs_t readoutTimestamp; int32_t transform; sp<ANativeWindowBuffer> anwBuffer; int releaseFence; BufferHolder(nsecs_t t, int32_t tr, ANativeWindowBuffer* anwb, int rf) : timestamp(t), transform(tr), anwBuffer(anwb), releaseFence(rf) {} BufferHolder(nsecs_t t, nsecs_t readoutT, int32_t tr, ANativeWindowBuffer* anwb, int rf) : timestamp(t), readoutTimestamp(readoutT), transform(tr), anwBuffer(anwb), releaseFence(rf) {} }; void queueBufferToClientLocked(const BufferHolder& bufferHolder, nsecs_t currentTime); Loading @@ -80,7 +82,7 @@ class PreviewFrameSpacer : public Thread { Condition mBufferCond; std::queue<BufferHolder> mPendingBuffers; nsecs_t mLastCameraCaptureTime = 0; nsecs_t mLastCameraReadoutTime = 0; nsecs_t mLastCameraPresentTime = 0; static constexpr nsecs_t kWaitDuration = 5000000LL; // 50ms static constexpr nsecs_t kFrameIntervalThreshold = 80000000LL; // 80ms Loading Loading
services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -89,9 +89,10 @@ void Camera3IOStreamBase::dump(int fd, const Vector<String16> &args) const { 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%" PRIx64, lines.appendFormat(" Dynamic Range Profile: 0x%" PRIx64 "\n", camera_stream::dynamic_range_profile); lines.appendFormat(" Stream use case: %" PRId64 "\n", camera_stream::use_case); lines.appendFormat(" Timestamp base: %d\n", getTimestampBase()); lines.appendFormat(" Frames produced: %d, last timestamp: %" PRId64 " ns\n", mFrameCount, mLastTimestamp); lines.appendFormat(" Total buffers: %zu, currently dequeued: %zu\n", Loading
services/camera/libcameraservice/device3/Camera3OutputStream.cpp +21 −5 Original line number Diff line number Diff line Loading @@ -466,8 +466,10 @@ status_t Camera3OutputStream::returnBufferCheckedLocked( nsecs_t captureTime = (mUseReadoutTime && readoutTimestamp != 0 ? readoutTimestamp : timestamp) - mTimestampOffset; if (mPreviewFrameSpacer != nullptr) { res = mPreviewFrameSpacer->queuePreviewBuffer(captureTime, transform, anwBuffer, anwReleaseFence); nsecs_t readoutTime = (readoutTimestamp != 0 ? readoutTimestamp : timestamp) - mTimestampOffset; res = mPreviewFrameSpacer->queuePreviewBuffer(captureTime, readoutTime, transform, anwBuffer, anwReleaseFence); if (res != OK) { ALOGE("%s: Stream %d: Error queuing buffer to preview buffer spacer: %s (%d)", __FUNCTION__, mId, strerror(-res), res); Loading Loading @@ -684,12 +686,15 @@ status_t Camera3OutputStream::configureConsumerQueueLocked(bool allowPreviewResp bool forceChoreographer = (timestampBase == OutputConfiguration::TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED); bool defaultToChoreographer = (isDefaultTimeBase && isConsumedByHWComposer() && !property_get_bool("camera.disable_preview_scheduler", false)); isConsumedByHWComposer()); bool defaultToSpacer = (isDefaultTimeBase && isConsumedByHWTexture() && !isConsumedByCPU() && !isVideoStream()); if (forceChoreographer || defaultToChoreographer) { mSyncToDisplay = true; mTotalBufferCount += kDisplaySyncExtraBuffer; } else if (isConsumedByHWTexture() && !isVideoStream()) { } else if (defaultToSpacer) { mPreviewFrameSpacer = new PreviewFrameSpacer(*this, mConsumer); mTotalBufferCount ++; res = mPreviewFrameSpacer->run(String8::format("PreviewSpacer-%d", mId).string()); Loading Loading @@ -1268,6 +1273,17 @@ bool Camera3OutputStream::isConsumedByHWTexture() const { return (usage & GRALLOC_USAGE_HW_TEXTURE) != 0; } bool Camera3OutputStream::isConsumedByCPU() const { uint64_t usage = 0; status_t res = getEndpointUsage(&usage); if (res != OK) { ALOGE("%s: getting end point usage failed: %s (%d).", __FUNCTION__, strerror(-res), res); return false; } return (usage & GRALLOC_USAGE_SW_READ_MASK) != 0; } void Camera3OutputStream::dumpImageToDisk(nsecs_t timestamp, ANativeWindowBuffer* anwBuffer, int fence) { // Deriver output file name Loading
services/camera/libcameraservice/device3/Camera3OutputStream.h +5 −0 Original line number Diff line number Diff line Loading @@ -159,6 +159,11 @@ class Camera3OutputStream : */ bool isConsumedByHWTexture() const; /** * Return if this output stream is consumed by CPU. */ bool isConsumedByCPU() const; /** * Return if the consumer configuration of this stream is deferred. */ Loading
services/camera/libcameraservice/device3/PreviewFrameSpacer.cpp +13 −13 Original line number Diff line number Diff line Loading @@ -36,12 +36,12 @@ PreviewFrameSpacer::~PreviewFrameSpacer() { Thread::requestExitAndWait(); } status_t PreviewFrameSpacer::queuePreviewBuffer(nsecs_t timestamp, int32_t transform, ANativeWindowBuffer* anwBuffer, int releaseFence) { status_t PreviewFrameSpacer::queuePreviewBuffer(nsecs_t timestamp, nsecs_t readoutTimestamp, int32_t transform, ANativeWindowBuffer* anwBuffer, int releaseFence) { Mutex::Autolock l(mLock); mPendingBuffers.emplace(timestamp, transform, anwBuffer, releaseFence); ALOGV("%s: mPendingBuffers size %zu, timestamp %" PRId64, __FUNCTION__, mPendingBuffers.size(), timestamp); mPendingBuffers.emplace(timestamp, readoutTimestamp, transform, anwBuffer, releaseFence); ALOGV("%s: mPendingBuffers size %zu, timestamp %" PRId64 ", readoutTime %" PRId64, __FUNCTION__, mPendingBuffers.size(), timestamp, readoutTimestamp); mBufferCond.signal(); return OK; Loading @@ -56,17 +56,17 @@ bool PreviewFrameSpacer::threadLoop() { nsecs_t currentTime = systemTime(); auto buffer = mPendingBuffers.front(); nsecs_t captureInterval = buffer.timestamp - mLastCameraCaptureTime; // If the capture interval exceeds threshold, directly queue nsecs_t readoutInterval = buffer.readoutTimestamp - mLastCameraReadoutTime; // If the readout interval exceeds threshold, directly queue // cached buffer. if (captureInterval >= kFrameIntervalThreshold) { if (readoutInterval >= kFrameIntervalThreshold) { mPendingBuffers.pop(); queueBufferToClientLocked(buffer, currentTime); return true; } // Cache the frame to match capture time interval, for up to 33ms nsecs_t expectedQueueTime = mLastCameraPresentTime + captureInterval; // Cache the frame to match readout time interval, for up to 33ms nsecs_t expectedQueueTime = mLastCameraPresentTime + readoutInterval; nsecs_t frameWaitTime = std::min(kMaxFrameWaitTime, expectedQueueTime - currentTime); if (frameWaitTime > 0 && mPendingBuffers.size() < 2) { mBufferCond.waitRelative(mLock, frameWaitTime); Loading @@ -75,8 +75,8 @@ bool PreviewFrameSpacer::threadLoop() { } currentTime = systemTime(); } ALOGV("%s: captureInterval %" PRId64 ", queueInterval %" PRId64 ", waited for %" PRId64 ", timestamp %" PRId64, __FUNCTION__, captureInterval, ALOGV("%s: readoutInterval %" PRId64 ", queueInterval %" PRId64 ", waited for %" PRId64 ", timestamp %" PRId64, __FUNCTION__, readoutInterval, currentTime - mLastCameraPresentTime, frameWaitTime, buffer.timestamp); mPendingBuffers.pop(); queueBufferToClientLocked(buffer, currentTime); Loading Loading @@ -114,7 +114,7 @@ void PreviewFrameSpacer::queueBufferToClientLocked( } mLastCameraPresentTime = currentTime; mLastCameraCaptureTime = bufferHolder.timestamp; mLastCameraReadoutTime = bufferHolder.readoutTimestamp; } }; // namespace camera3 Loading
services/camera/libcameraservice/device3/PreviewFrameSpacer.h +9 −7 Original line number Diff line number Diff line Loading @@ -42,8 +42,8 @@ class Camera3OutputStream; * * The PreviewFrameSpacer improves the viewfinder user experience by: * - Cache the frame buffers if the intervals between queueBuffer is shorter * than the camera capture intervals. * - Queue frame buffers in the same cadence as the camera capture time. * than the camera readout intervals. * - Queue frame buffers in the same cadence as the camera readout time. * - Maintain at most 1 queue-able buffer. If the 2nd preview buffer becomes * available, queue the oldest cached buffer to the buffer queue. */ Loading @@ -53,8 +53,8 @@ class PreviewFrameSpacer : public Thread { virtual ~PreviewFrameSpacer(); // Queue preview buffer locally status_t queuePreviewBuffer(nsecs_t timestamp, int32_t transform, ANativeWindowBuffer* anwBuffer, int releaseFence); status_t queuePreviewBuffer(nsecs_t timestamp, nsecs_t readoutTimestamp, int32_t transform, ANativeWindowBuffer* anwBuffer, int releaseFence); bool threadLoop() override; void requestExit() override; Loading @@ -63,12 +63,14 @@ class PreviewFrameSpacer : public Thread { // structure holding cached preview buffer info struct BufferHolder { nsecs_t timestamp; nsecs_t readoutTimestamp; int32_t transform; sp<ANativeWindowBuffer> anwBuffer; int releaseFence; BufferHolder(nsecs_t t, int32_t tr, ANativeWindowBuffer* anwb, int rf) : timestamp(t), transform(tr), anwBuffer(anwb), releaseFence(rf) {} BufferHolder(nsecs_t t, nsecs_t readoutT, int32_t tr, ANativeWindowBuffer* anwb, int rf) : timestamp(t), readoutTimestamp(readoutT), transform(tr), anwBuffer(anwb), releaseFence(rf) {} }; void queueBufferToClientLocked(const BufferHolder& bufferHolder, nsecs_t currentTime); Loading @@ -80,7 +82,7 @@ class PreviewFrameSpacer : public Thread { Condition mBufferCond; std::queue<BufferHolder> mPendingBuffers; nsecs_t mLastCameraCaptureTime = 0; nsecs_t mLastCameraReadoutTime = 0; nsecs_t mLastCameraPresentTime = 0; static constexpr nsecs_t kWaitDuration = 5000000LL; // 50ms static constexpr nsecs_t kFrameIntervalThreshold = 80000000LL; // 80ms Loading