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

Commit 4cd86726 authored by Nipun Kwatra's avatar Nipun Kwatra
Browse files

Restart preview after each takePicture is done.

Preview is called when CAMERA_MSG_COMPRESSED_IMAGE is recieved by
dataCallback(). It needs to be started as a new thread so that the
callback can return, and the camera can know that takePicture() is
done.

Change-Id: I4d0febbc993aac43b37f9f4a824e9c7b8785f19e
parent 97a25663
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;
    }