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

Commit 6fbc20c9 authored by Shuzhen Wang's avatar Shuzhen Wang Committed by Android (Google) Code Review
Browse files

Merge "Camera: Retry JPEG capture if buffer is dropped." into nyc-dev

parents c1c545a2 b0fdc1ed
Loading
Loading
Loading
Loading
+18 −1
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ CaptureSequencer::CaptureSequencer(wp<Camera2Client> client):
        mNewAEState(false),
        mNewFrameReceived(false),
        mNewCaptureReceived(false),
        mNewCaptureErrorCnt(0),
        mShutterNotified(false),
        mHalNotifiedShutter(false),
        mShutterCaptureId(-1),
@@ -131,7 +132,7 @@ void CaptureSequencer::onResultAvailable(const CaptureResult &result) {
}

void CaptureSequencer::onCaptureAvailable(nsecs_t timestamp,
        sp<MemoryBase> captureBuffer) {
        sp<MemoryBase> captureBuffer, bool captureError) {
    ATRACE_CALL();
    ALOGV("%s", __FUNCTION__);
    Mutex::Autolock l(mInputMutex);
@@ -139,6 +140,11 @@ void CaptureSequencer::onCaptureAvailable(nsecs_t timestamp,
    mCaptureBuffer = captureBuffer;
    if (!mNewCaptureReceived) {
        mNewCaptureReceived = true;
        if (captureError) {
            mNewCaptureErrorCnt++;
        } else {
            mNewCaptureErrorCnt = 0;
        }
        mNewCaptureSignal.signal();
    }
}
@@ -623,6 +629,17 @@ CaptureSequencer::CaptureState CaptureSequencer::manageStandardCaptureWait(
            break;
        }
    }
    if (mNewCaptureReceived) {
        if (mNewCaptureErrorCnt > kMaxRetryCount) {
            ALOGW("Exceeding multiple retry limit of %d due to buffer drop", kMaxRetryCount);
            return DONE;
        } else if (mNewCaptureErrorCnt > 0) {
            ALOGW("Capture error happened, retry %d...", mNewCaptureErrorCnt);
            mNewCaptureReceived = false;
            return STANDARD_CAPTURE;
        }
    }

    if (mTimeoutCount <= 0) {
        ALOGW("Timed out waiting for capture to complete");
        return DONE;
+3 −1
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ class CaptureSequencer:
    virtual void onResultAvailable(const CaptureResult &result);

    // Notifications from the JPEG processor
    void onCaptureAvailable(nsecs_t timestamp, sp<MemoryBase> captureBuffer);
    void onCaptureAvailable(nsecs_t timestamp, sp<MemoryBase> captureBuffer, bool captureError);

    void dump(int fd, const Vector<String16>& args);

@@ -94,6 +94,7 @@ class CaptureSequencer:
    Condition mNewFrameSignal;

    bool mNewCaptureReceived;
    int32_t mNewCaptureErrorCnt;
    nsecs_t mCaptureTimestamp;
    sp<MemoryBase> mCaptureBuffer;
    Condition mNewCaptureSignal;
@@ -110,6 +111,7 @@ class CaptureSequencer:
    static const int kMaxTimeoutsForPrecaptureStart = 10; // 1 sec
    static const int kMaxTimeoutsForPrecaptureEnd = 20;  // 2 sec
    static const int kMaxTimeoutsForCaptureEnd    = 40;  // 4 sec
    static const int kMaxRetryCount = 3; // 3 retries in case of buffer drop

    wp<Camera2Client> mClient;
    wp<ZslProcessor> mZslProcessor;
+39 −13
Original line number Diff line number Diff line
@@ -42,7 +42,8 @@ JpegProcessor::JpegProcessor(
        mDevice(client->getCameraDevice()),
        mSequencer(sequencer),
        mId(client->getCameraId()),
        mCaptureAvailable(false),
        mCaptureDone(false),
        mCaptureSuccess(false),
        mCaptureStreamId(NO_STREAM) {
}

@@ -53,9 +54,26 @@ JpegProcessor::~JpegProcessor() {

void JpegProcessor::onFrameAvailable(const BufferItem& /*item*/) {
    Mutex::Autolock l(mInputMutex);
    if (!mCaptureAvailable) {
        mCaptureAvailable = true;
        mCaptureAvailableSignal.signal();
    ALOGV("%s", __FUNCTION__);
    if (!mCaptureDone) {
        mCaptureDone = true;
        mCaptureSuccess = true;
        mCaptureDoneSignal.signal();
    }
}

void JpegProcessor::onBufferAcquired(const BufferInfo& /*bufferInfo*/) {
    // Intentionally left empty
}

void JpegProcessor::onBufferReleased(const BufferInfo& bufferInfo) {
    Mutex::Autolock l(mInputMutex);
    ALOGV("%s", __FUNCTION__);

    if (bufferInfo.mError) {
        mCaptureDone = true;
        mCaptureSuccess = false;
        mCaptureDoneSignal.signal();
    }
}

@@ -154,6 +172,12 @@ status_t JpegProcessor::updateStream(const Parameters &params) {
            return res;
        }

        res = device->addBufferListenerForStream(mCaptureStreamId, this);
        if (res != OK) {
              ALOGE("%s: Camera %d: Can't add buffer listeneri: %s (%d)",
                    __FUNCTION__, mId, strerror(-res), res);
              return res;
        }
    }
    return OK;
}
@@ -192,24 +216,26 @@ void JpegProcessor::dump(int /*fd*/, const Vector<String16>& /*args*/) const {
bool JpegProcessor::threadLoop() {
    status_t res;

    bool captureSuccess = false;
    {
        Mutex::Autolock l(mInputMutex);
        while (!mCaptureAvailable) {
            res = mCaptureAvailableSignal.waitRelative(mInputMutex,

        while (!mCaptureDone) {
            res = mCaptureDoneSignal.waitRelative(mInputMutex,
                    kWaitDuration);
            if (res == TIMED_OUT) return true;
        }
        mCaptureAvailable = false;

        captureSuccess = mCaptureSuccess;
        mCaptureDone = false;
    }

    do {
        res = processNewCapture();
    } while (res == OK);
    res = processNewCapture(captureSuccess);

    return true;
}

status_t JpegProcessor::processNewCapture() {
status_t JpegProcessor::processNewCapture(bool captureSuccess) {
    ATRACE_CALL();
    status_t res;
    sp<Camera2Heap> captureHeap;
@@ -217,7 +243,7 @@ status_t JpegProcessor::processNewCapture() {

    CpuConsumer::LockedBuffer imgBuffer;

    {
    if (captureSuccess) {
        Mutex::Autolock l(mInputMutex);
        if (mCaptureStreamId == NO_STREAM) {
            ALOGW("%s: Camera %d: No stream is available", __FUNCTION__, mId);
@@ -269,7 +295,7 @@ status_t JpegProcessor::processNewCapture() {

    sp<CaptureSequencer> sequencer = mSequencer.promote();
    if (sequencer != 0) {
        sequencer->onCaptureAvailable(imgBuffer.timestamp, captureBuffer);
        sequencer->onCaptureAvailable(imgBuffer.timestamp, captureBuffer, !captureSuccess);
    }

    return OK;
+10 −4
Original line number Diff line number Diff line
@@ -41,7 +41,8 @@ struct Parameters;
 * Still image capture output image processing
 */
class JpegProcessor:
            public Thread, public CpuConsumer::FrameAvailableListener {
            public Thread, public CpuConsumer::FrameAvailableListener,
            public camera3::Camera3StreamBufferListener {
  public:
    JpegProcessor(sp<Camera2Client> client, wp<CaptureSequencer> sequencer);
    ~JpegProcessor();
@@ -49,6 +50,10 @@ class JpegProcessor:
    // CpuConsumer listener implementation
    void onFrameAvailable(const BufferItem& item);

    // Camera3StreamBufferListener implementation
    void onBufferAcquired(const BufferInfo& bufferInfo) override;
    void onBufferReleased(const BufferInfo& bufferInfo) override;

    status_t updateStream(const Parameters &params);
    status_t deleteStream();
    int getStreamId() const;
@@ -61,8 +66,9 @@ class JpegProcessor:
    int mId;

    mutable Mutex mInputMutex;
    bool mCaptureAvailable;
    Condition mCaptureAvailableSignal;
    bool mCaptureDone;
    bool mCaptureSuccess;
    Condition mCaptureDoneSignal;

    enum {
        NO_STREAM = -1
@@ -75,7 +81,7 @@ class JpegProcessor:

    virtual bool threadLoop();

    status_t processNewCapture();
    status_t processNewCapture(bool captureSuccess);
    size_t findJpegSize(uint8_t* jpegBuffer, size_t maxSize);

};
+6 −0
Original line number Diff line number Diff line
@@ -295,6 +295,12 @@ class CameraDeviceBase : public virtual RefBase {
     */
    virtual status_t tearDown(int streamId) = 0;

    /**
     * Add buffer listener for a particular stream in the device.
     */
    virtual status_t addBufferListenerForStream(int streamId,
            wp<camera3::Camera3StreamBufferListener> listener) = 0;

    /**
     * Prepare stream by preallocating up to maxCount buffers for it asynchronously.
     * Calls notifyPrepared() once allocation is complete.
Loading