CameraSourceTimeLapse.cpp revision fd150a8e03cdd8462eafd68f4a4231aa52f0e5a1
165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra/*
265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra * Copyright (C) 2010 The Android Open Source Project
365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra *
465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra * Licensed under the Apache License, Version 2.0 (the "License");
565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra * you may not use this file except in compliance with the License.
665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra * You may obtain a copy of the License at
765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra *
865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra *      http://www.apache.org/licenses/LICENSE-2.0
965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra *
1065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra * Unless required by applicable law or agreed to in writing, software
1165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra * distributed under the License is distributed on an "AS IS" BASIS,
1265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra * See the License for the specific language governing permissions and
1465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra * limitations under the License.
1565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra */
1665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
1765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra//#define LOG_NDEBUG 0
1865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#define LOG_TAG "CameraSourceTimeLapse"
1965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
2065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <binder/IPCThreadState.h>
2165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <binder/MemoryBase.h>
2265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <binder/MemoryHeapBase.h>
2365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <media/stagefright/CameraSource.h>
2465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <media/stagefright/CameraSourceTimeLapse.h>
2565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <media/stagefright/MediaDebug.h>
2665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <media/stagefright/MetaData.h>
27c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra#include <media/stagefright/YUVImage.h>
28c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra#include <media/stagefright/YUVCanvas.h>
2965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <camera/Camera.h>
3065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <camera/CameraParameters.h>
31c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra#include <ui/Rect.h>
3265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <utils/String8.h>
3340e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra#include <utils/Vector.h>
34c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra#include "OMX_Video.h"
35fd150a8e03cdd8462eafd68f4a4231aa52f0e5a1Nipun Kwatra#include <limits.h>
3665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
3765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatranamespace android {
3865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
3965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra// static
4065e7e6facda89927cb26594b3b65ae81b3235ebcNipun KwatraCameraSourceTimeLapse *CameraSourceTimeLapse::Create(bool useStillCameraForTimeLapse,
4165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        int64_t timeBetweenTimeLapseFrameCaptureUs,
42e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        int32_t width, int32_t height,
4365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        int32_t videoFrameRate) {
4465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    sp<Camera> camera = Camera::connect(0);
4565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
4665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    if (camera.get() == NULL) {
4765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return NULL;
4865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
4965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
5065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    return new CameraSourceTimeLapse(camera, useStillCameraForTimeLapse,
51e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra            timeBetweenTimeLapseFrameCaptureUs, width, height, videoFrameRate);
5265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
5365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
5465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra// static
5565e7e6facda89927cb26594b3b65ae81b3235ebcNipun KwatraCameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera(const sp<Camera> &camera,
5665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        bool useStillCameraForTimeLapse,
5765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        int64_t timeBetweenTimeLapseFrameCaptureUs,
58e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        int32_t width, int32_t height,
5965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        int32_t videoFrameRate) {
6065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    if (camera.get() == NULL) {
6165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return NULL;
6265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
6365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
6465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    return new CameraSourceTimeLapse(camera, useStillCameraForTimeLapse,
65e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra            timeBetweenTimeLapseFrameCaptureUs, width, height, videoFrameRate);
6665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
6765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
6865e7e6facda89927cb26594b3b65ae81b3235ebcNipun KwatraCameraSourceTimeLapse::CameraSourceTimeLapse(const sp<Camera> &camera,
6965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        bool useStillCameraForTimeLapse,
7065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        int64_t timeBetweenTimeLapseFrameCaptureUs,
71e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        int32_t width, int32_t height,
7265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        int32_t videoFrameRate)
7365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    : CameraSource(camera),
7465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mUseStillCameraForTimeLapse(useStillCameraForTimeLapse),
7565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mTimeBetweenTimeLapseFrameCaptureUs(timeBetweenTimeLapseFrameCaptureUs),
7665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mTimeBetweenTimeLapseVideoFramesUs(1E6/videoFrameRate),
7765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mLastTimeLapseFrameRealTimestampUs(0),
7865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mSkipCurrentFrame(false) {
7965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
8065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    LOGV("starting time lapse mode");
81c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    mVideoWidth = width;
82c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    mVideoHeight = height;
83c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (mUseStillCameraForTimeLapse) {
8440e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra        CHECK(setPictureSizeToClosestSupported(width, height));
85c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        mNeedCropping = computeCropRectangleOffset();
8665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        mMeta->setInt32(kKeyWidth, width);
8765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        mMeta->setInt32(kKeyHeight, height);
8865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
8965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
9065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
9165e7e6facda89927cb26594b3b65ae81b3235ebcNipun KwatraCameraSourceTimeLapse::~CameraSourceTimeLapse() {
9265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
9365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
9440e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatrabool CameraSourceTimeLapse::setPictureSizeToClosestSupported(int32_t width, int32_t height) {
9540e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    int64_t token = IPCThreadState::self()->clearCallingIdentity();
9640e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    String8 s = mCamera->getParameters();
9740e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    IPCThreadState::self()->restoreCallingIdentity(token);
9840e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra
9940e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    CameraParameters params(s);
10040e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    Vector<Size> supportedSizes;
10140e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    params.getSupportedPictureSizes(supportedSizes);
10240e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra
10340e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    int32_t minPictureSize = INT_MAX;
10440e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    for (uint32_t i = 0; i < supportedSizes.size(); ++i) {
10540e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra        int32_t pictureWidth = supportedSizes[i].width;
10640e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra        int32_t pictureHeight = supportedSizes[i].height;
10740e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra
10840e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra        if ((pictureWidth >= width) && (pictureHeight >= height)) {
10940e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra            int32_t pictureSize = pictureWidth*pictureHeight;
11040e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra            if (pictureSize < minPictureSize) {
11140e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra                minPictureSize = pictureSize;
11240e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra                mPictureWidth = pictureWidth;
11340e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra                mPictureHeight = pictureHeight;
11440e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra            }
11540e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra        }
11640e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    }
11740e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    LOGV("Picture size = (%d, %d)", mPictureWidth, mPictureHeight);
11840e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    return (minPictureSize != INT_MAX);
119c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra}
120c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
121c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatrabool CameraSourceTimeLapse::computeCropRectangleOffset() {
122c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if ((mPictureWidth == mVideoWidth) && (mPictureHeight == mVideoHeight)) {
123c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        return false;
124c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    }
125c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
126c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    CHECK((mPictureWidth > mVideoWidth) && (mPictureHeight > mVideoHeight));
127c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
128c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    int32_t widthDifference = mPictureWidth - mVideoWidth;
129c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    int32_t heightDifference = mPictureHeight - mVideoHeight;
130c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
131c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    mCropRectStartX = widthDifference/2;
132c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    mCropRectStartY = heightDifference/2;
133c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
134c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    LOGV("setting crop rectangle offset to (%d, %d)", mCropRectStartX, mCropRectStartY);
135c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
136c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    return true;
137c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra}
138c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
13965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra// static
14065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid *CameraSourceTimeLapse::ThreadTimeLapseWrapper(void *me) {
14165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me);
14265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    source->threadTimeLapseEntry();
14365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    return NULL;
14465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
14565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
14665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::threadTimeLapseEntry() {
14765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    while(mStarted) {
148c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        if (mCameraIdle) {
1490aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra            LOGV("threadTimeLapseEntry: taking picture");
1500aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra            CHECK_EQ(OK, mCamera->takePicture());
1510aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra            mCameraIdle = false;
1520aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra            sleep(mTimeBetweenTimeLapseFrameCaptureUs/1E6);
1530aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra        } else {
1540aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra            LOGV("threadTimeLapseEntry: camera busy with old takePicture. Sleeping a little.");
1550aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra            sleep(.01);
1560aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra        }
15765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
15865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
15965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
16065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::startCameraRecording() {
161c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (mUseStillCameraForTimeLapse) {
16265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        LOGV("start time lapse recording using still camera");
16365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
16465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        int64_t token = IPCThreadState::self()->clearCallingIdentity();
16565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        String8 s = mCamera->getParameters();
16665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        IPCThreadState::self()->restoreCallingIdentity(token);
16765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
16865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        CameraParameters params(s);
169c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        params.setPictureSize(mPictureWidth, mPictureHeight);
17065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        mCamera->setParameters(params.flatten());
1710aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra        mCameraIdle = true;
17265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
17365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        // create a thread which takes pictures in a loop
17465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        pthread_attr_t attr;
17565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        pthread_attr_init(&attr);
17665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
17765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
17865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        pthread_create(&mThreadTimeLapse, &attr, ThreadTimeLapseWrapper, this);
17965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        pthread_attr_destroy(&attr);
18065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    } else {
18165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        LOGV("start time lapse recording using video camera");
18265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        CHECK_EQ(OK, mCamera->startRecording());
18365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
18465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
18565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
18665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::stopCameraRecording() {
187c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (mUseStillCameraForTimeLapse) {
18865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        void *dummy;
18965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        pthread_join(mThreadTimeLapse, &dummy);
19065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    } else {
19165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        mCamera->stopRecording();
19265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
19365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
19465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
19565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::releaseRecordingFrame(const sp<IMemory>& frame) {
196c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (!mUseStillCameraForTimeLapse) {
19765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        mCamera->releaseRecordingFrame(frame);
19865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
19965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
20065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
20165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatrasp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(const sp<IMemory> &source_data) {
20265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    size_t source_size = source_data->size();
20365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    void* source_pointer = source_data->pointer();
20465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
20565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    sp<MemoryHeapBase> newMemoryHeap = new MemoryHeapBase(source_size);
20665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    sp<MemoryBase> newMemory = new MemoryBase(newMemoryHeap, 0, source_size);
20765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    memcpy(newMemory->pointer(), source_pointer, source_size);
20865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    return newMemory;
20965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
21065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
211c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra// Allocates IMemory of final type MemoryBase with the given size.
212c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatrasp<IMemory> allocateIMemory(size_t size) {
213c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    sp<MemoryHeapBase> newMemoryHeap = new MemoryHeapBase(size);
214c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    sp<MemoryBase> newMemory = new MemoryBase(newMemoryHeap, 0, size);
215c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    return newMemory;
216c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra}
217c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
2180aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra// static
2190aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatravoid *CameraSourceTimeLapse::ThreadStartPreviewWrapper(void *me) {
2200aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me);
2210aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    source->threadStartPreview();
2220aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    return NULL;
2230aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra}
2240aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra
2250aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatravoid CameraSourceTimeLapse::threadStartPreview() {
2260aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    CHECK_EQ(OK, mCamera->startPreview());
2270aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    mCameraIdle = true;
2280aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra}
2290aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra
2300aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatravoid CameraSourceTimeLapse::restartPreview() {
2310aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    // Start this in a different thread, so that the dataCallback can return
2320aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    LOGV("restartPreview");
2330aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    pthread_attr_t attr;
2340aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    pthread_attr_init(&attr);
2350aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2360aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra
2370aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    pthread_t threadPreview;
2380aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    pthread_create(&threadPreview, &attr, ThreadStartPreviewWrapper, this);
2390aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    pthread_attr_destroy(&attr);
2400aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra}
2410aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra
242c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatrasp<IMemory> CameraSourceTimeLapse::cropYUVImage(const sp<IMemory> &source_data) {
243c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    // find the YUV format
244c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    int32_t srcFormat;
245c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    CHECK(mMeta->findInt32(kKeyColorFormat, &srcFormat));
246c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    YUVImage::YUVFormat yuvFormat;
247c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (srcFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
248c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        yuvFormat = YUVImage::YUV420SemiPlanar;
249c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    } else if (srcFormat == OMX_COLOR_FormatYUV420Planar) {
250c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        yuvFormat = YUVImage::YUV420Planar;
251c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    }
252c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
253c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    // allocate memory for cropped image and setup a canvas using it.
254c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    sp<IMemory> croppedImageMemory = allocateIMemory(
255c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra            YUVImage::bufferSize(yuvFormat, mVideoWidth, mVideoHeight));
256c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    YUVImage yuvImageCropped(yuvFormat,
257c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra            mVideoWidth, mVideoHeight,
258c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra            (uint8_t *)croppedImageMemory->pointer());
259c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    YUVCanvas yuvCanvasCrop(yuvImageCropped);
260c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
261c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    YUVImage yuvImageSource(yuvFormat,
262c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra            mPictureWidth, mPictureHeight,
263c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra            (uint8_t *)source_data->pointer());
264c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    yuvCanvasCrop.CopyImageRect(
265c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra            Rect(mCropRectStartX, mCropRectStartY,
266c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra                mCropRectStartX + mVideoWidth,
267c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra                mCropRectStartY + mVideoHeight),
268c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra            0, 0,
269c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra            yuvImageSource);
270c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
271c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    return croppedImageMemory;
272c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra}
273c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
27465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::dataCallback(int32_t msgType, const sp<IMemory> &data) {
275c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (msgType == CAMERA_MSG_COMPRESSED_IMAGE) {
2760aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra        // takePicture will complete after this callback, so restart preview.
2770aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra        restartPreview();
278c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        return;
2790aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    }
280c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (msgType != CAMERA_MSG_RAW_IMAGE) {
28165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return;
28265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
28365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
28465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    LOGV("dataCallback for timelapse still frame");
28565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    CHECK_EQ(true, mUseStillCameraForTimeLapse);
28665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
28765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    int64_t timestampUs;
28865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    if (mNumFramesReceived == 0) {
28965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        timestampUs = mStartTimeUs;
29065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    } else {
29165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
29265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
293c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
294c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (mNeedCropping) {
295c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        sp<IMemory> croppedImageData = cropYUVImage(data);
296c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        dataCallbackTimestamp(timestampUs, msgType, croppedImageData);
297c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    } else {
298c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        sp<IMemory> dataCopy = createIMemoryCopy(data);
299c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        dataCallbackTimestamp(timestampUs, msgType, dataCopy);
300c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    }
30165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
30265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
30365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatrabool CameraSourceTimeLapse::skipCurrentFrame(int64_t timestampUs) {
304c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (mSkipCurrentFrame) {
30565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        mSkipCurrentFrame = false;
30665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return true;
30765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    } else {
30865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return false;
30965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
31065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
31165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
31265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatrabool CameraSourceTimeLapse::skipFrameAndModifyTimeStamp(int64_t *timestampUs) {
313c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (!mUseStillCameraForTimeLapse) {
314c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        if (mLastTimeLapseFrameRealTimestampUs == 0) {
31565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // First time lapse frame. Initialize mLastTimeLapseFrameRealTimestampUs
31665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // to current time (timestampUs) and save frame data.
31765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            LOGV("dataCallbackTimestamp timelapse: initial frame");
31865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
31965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            mLastTimeLapseFrameRealTimestampUs = *timestampUs;
32065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        } else if (*timestampUs <
32165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra                (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenTimeLapseFrameCaptureUs)) {
32265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // Skip all frames from last encoded frame until
32365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // sufficient time (mTimeBetweenTimeLapseFrameCaptureUs) has passed.
32465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // Tell the camera to release its recording frame and return.
32565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            LOGV("dataCallbackTimestamp timelapse: skipping intermediate frame");
32665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            return true;
32765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        } else {
32865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // Desired frame has arrived after mTimeBetweenTimeLapseFrameCaptureUs time:
32965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // - Reset mLastTimeLapseFrameRealTimestampUs to current time.
33065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // - Artificially modify timestampUs to be one frame time (1/framerate) ahead
33165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // of the last encoded frame's time stamp.
33265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            LOGV("dataCallbackTimestamp timelapse: got timelapse frame");
33365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
33465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            mLastTimeLapseFrameRealTimestampUs = *timestampUs;
33565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
33665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        }
33765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
33865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    return false;
33965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
34065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
34165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
34265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            const sp<IMemory> &data) {
343c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (!mUseStillCameraForTimeLapse) {
34465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        mSkipCurrentFrame = skipFrameAndModifyTimeStamp(&timestampUs);
34565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
34665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    CameraSource::dataCallbackTimestamp(timestampUs, msgType, data);
34765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
34865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
34965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}  // namespace android
350