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

Commit 87419a2b authored by Nipun Kwatra's avatar Nipun Kwatra Committed by Android (Google) Code Review
Browse files

Merge "Restart preview after each takePicture is done."

parents bcfdb328 4cd86726
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ namespace android {

class ICamera;
class IMemory;
class ISurface;
class Camera;

class CameraSourceTimeLapse : public CameraSource {
@@ -65,6 +64,9 @@ private:
    // to know if current frame needs to be skipped.
    bool mSkipCurrentFrame;

    // True if camera is in preview mode and ready for takePicture().
    bool mCameraIdle;

    CameraSourceTimeLapse(const sp<Camera> &camera,
        bool useStillCameraForTimeLapse,
        int64_t timeBetweenTimeLapseFrameCaptureUs,
@@ -117,6 +119,17 @@ private:
    // Used only in the case mUseStillCameraForTimeLapse = true.
    void threadTimeLapseEntry();

    // Wrapper to enter threadStartPreview()
    static void *ThreadStartPreviewWrapper(void *me);

    // Starts the camera's preview.
    void threadStartPreview();

    // Starts thread ThreadStartPreviewWrapper() for restarting preview.
    // Needs to be done in a thread so that dataCallback() which calls this function
    // can return, and the camera can know that takePicture() is done.
    void restartPreview();

    // Creates a copy of source_data into a new memory of final type MemoryBase.
    sp<IMemory> createIMemoryCopy(const sp<IMemory> &source_data);

+38 −6
Original line number Diff line number Diff line
@@ -92,9 +92,15 @@ void *CameraSourceTimeLapse::ThreadTimeLapseWrapper(void *me) {

void CameraSourceTimeLapse::threadTimeLapseEntry() {
    while(mStarted) {
        LOGV("threadTimeLapseEntry loop");
        sleep(mTimeBetweenTimeLapseFrameCaptureUs/1E6);
        if(mCameraIdle) {
            LOGV("threadTimeLapseEntry: taking picture");
            CHECK_EQ(OK, mCamera->takePicture());
            mCameraIdle = false;
            sleep(mTimeBetweenTimeLapseFrameCaptureUs/1E6);
        } else {
            LOGV("threadTimeLapseEntry: camera busy with old takePicture. Sleeping a little.");
            sleep(.01);
        }
    }
}

@@ -112,11 +118,9 @@ void CameraSourceTimeLapse::startCameraRecording() {
        IPCThreadState::self()->restoreCallingIdentity(token);

        CameraParameters params(s);

        params.setPictureSize(width, height);
        mCamera->setParameters(params.flatten());

        CHECK_EQ(OK, mCamera->takePicture());
        mCameraIdle = true;

        // create a thread which takes pictures in a loop
        pthread_attr_t attr;
@@ -156,7 +160,35 @@ sp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(const sp<IMemory> &source_d
    return newMemory;
}

// static
void *CameraSourceTimeLapse::ThreadStartPreviewWrapper(void *me) {
    CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me);
    source->threadStartPreview();
    return NULL;
}

void CameraSourceTimeLapse::threadStartPreview() {
    CHECK_EQ(OK, mCamera->startPreview());
    mCameraIdle = true;
}

void CameraSourceTimeLapse::restartPreview() {
    // Start this in a different thread, so that the dataCallback can return
    LOGV("restartPreview");
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    pthread_t threadPreview;
    pthread_create(&threadPreview, &attr, ThreadStartPreviewWrapper, this);
    pthread_attr_destroy(&attr);
}

void CameraSourceTimeLapse::dataCallback(int32_t msgType, const sp<IMemory> &data) {
    if(msgType == CAMERA_MSG_COMPRESSED_IMAGE) {
        // takePicture will complete after this callback, so restart preview.
        restartPreview();
    }
    if(msgType != CAMERA_MSG_RAW_IMAGE) {
        return;
    }