CameraSourceTimeLapse.cpp revision 78eff720c86eb6d4e3d45a144df60b2ca464d2d4
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
40155e833a7a5fc3e193691324cf9326da1bc3289aNipun KwatraCameraSourceTimeLapse *CameraSourceTimeLapse::Create(
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
50155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    return new CameraSourceTimeLapse(camera, timeBetweenTimeLapseFrameCaptureUs,
51155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra            width, height, videoFrameRate);
5265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
5365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
5465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra// static
5565e7e6facda89927cb26594b3b65ae81b3235ebcNipun KwatraCameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera(const sp<Camera> &camera,
5665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        int64_t timeBetweenTimeLapseFrameCaptureUs,
57e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        int32_t width, int32_t height,
5865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        int32_t videoFrameRate) {
5965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    if (camera.get() == NULL) {
6065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return NULL;
6165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
6265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
63155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    return new CameraSourceTimeLapse(camera, timeBetweenTimeLapseFrameCaptureUs,
64155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra            width, height, videoFrameRate);
6565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
6665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
6765e7e6facda89927cb26594b3b65ae81b3235ebcNipun KwatraCameraSourceTimeLapse::CameraSourceTimeLapse(const sp<Camera> &camera,
6865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        int64_t timeBetweenTimeLapseFrameCaptureUs,
69e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra        int32_t width, int32_t height,
7065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        int32_t videoFrameRate)
7165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    : CameraSource(camera),
7265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mTimeBetweenTimeLapseFrameCaptureUs(timeBetweenTimeLapseFrameCaptureUs),
7365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mTimeBetweenTimeLapseVideoFramesUs(1E6/videoFrameRate),
7465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mLastTimeLapseFrameRealTimestampUs(0),
7565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mSkipCurrentFrame(false) {
7665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
7765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    LOGV("starting time lapse mode");
78c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    mVideoWidth = width;
79c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    mVideoHeight = height;
80155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra
81155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    if (trySettingPreviewSize(width, height)) {
82155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra        mUseStillCameraForTimeLapse = false;
83155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    } else {
84155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra        // TODO: Add a check to see that mTimeBetweenTimeLapseFrameCaptureUs is greater
85155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra        // than the fastest rate at which the still camera can take pictures.
86155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra        mUseStillCameraForTimeLapse = true;
8740e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra        CHECK(setPictureSizeToClosestSupported(width, height));
88c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        mNeedCropping = computeCropRectangleOffset();
8965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        mMeta->setInt32(kKeyWidth, width);
9065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        mMeta->setInt32(kKeyHeight, height);
9165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
9278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
9378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    // Initialize quick stop variables.
9478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mQuickStop = false;
9578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mForceRead = false;
9678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mLastReadBufferCopy = NULL;
9778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mStopWaitingForIdleCamera = false;
9865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
9965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
10065e7e6facda89927cb26594b3b65ae81b3235ebcNipun KwatraCameraSourceTimeLapse::~CameraSourceTimeLapse() {
10165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
10265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
10378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatravoid CameraSourceTimeLapse::startQuickReadReturns() {
10478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    Mutex::Autolock autoLock(mQuickStopLock);
10578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    LOGV("Enabling quick read returns");
10678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
10778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    // Enable quick stop mode.
10878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mQuickStop = true;
10978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
11078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    if (mUseStillCameraForTimeLapse) {
11178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // wake up the thread right away.
11278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        mTakePictureCondition.signal();
11378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    } else {
11478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // Force dataCallbackTimestamp() coming from the video camera to not skip the
11578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // next frame as we want read() to get a get a frame right away.
11678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        mForceRead = true;
11778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    }
11878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra}
11978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
120155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatrabool CameraSourceTimeLapse::trySettingPreviewSize(int32_t width, int32_t height) {
121155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    int64_t token = IPCThreadState::self()->clearCallingIdentity();
122155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    String8 s = mCamera->getParameters();
123155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    IPCThreadState::self()->restoreCallingIdentity(token);
124155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra
125155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    CameraParameters params(s);
126155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    Vector<Size> supportedSizes;
127155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    params.getSupportedPreviewSizes(supportedSizes);
128155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra
129155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    bool previewSizeSupported = false;
130155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    for (uint32_t i = 0; i < supportedSizes.size(); ++i) {
131155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra        int32_t pictureWidth = supportedSizes[i].width;
132155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra        int32_t pictureHeight = supportedSizes[i].height;
133155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra
134155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra        if ((pictureWidth == width) && (pictureHeight == height)) {
135155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra            previewSizeSupported = true;
136155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra        }
137155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    }
138155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra
139155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    if (previewSizeSupported) {
140155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra        LOGV("Video size (%d, %d) is a supported preview size", width, height);
141155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra        params.setPreviewSize(width, height);
142155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra        CHECK(mCamera->setParameters(params.flatten()));
143155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra        return true;
144155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    }
145155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra
146155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    return false;
147155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra}
148155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra
14940e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatrabool CameraSourceTimeLapse::setPictureSizeToClosestSupported(int32_t width, int32_t height) {
15040e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    int64_t token = IPCThreadState::self()->clearCallingIdentity();
15140e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    String8 s = mCamera->getParameters();
15240e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    IPCThreadState::self()->restoreCallingIdentity(token);
15340e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra
15440e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    CameraParameters params(s);
15540e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    Vector<Size> supportedSizes;
15640e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    params.getSupportedPictureSizes(supportedSizes);
15740e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra
15840e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    int32_t minPictureSize = INT_MAX;
15940e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    for (uint32_t i = 0; i < supportedSizes.size(); ++i) {
16040e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra        int32_t pictureWidth = supportedSizes[i].width;
16140e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra        int32_t pictureHeight = supportedSizes[i].height;
16240e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra
16340e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra        if ((pictureWidth >= width) && (pictureHeight >= height)) {
16440e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra            int32_t pictureSize = pictureWidth*pictureHeight;
16540e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra            if (pictureSize < minPictureSize) {
16640e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra                minPictureSize = pictureSize;
16740e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra                mPictureWidth = pictureWidth;
16840e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra                mPictureHeight = pictureHeight;
16940e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra            }
17040e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra        }
17140e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    }
17240e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    LOGV("Picture size = (%d, %d)", mPictureWidth, mPictureHeight);
17340e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra    return (minPictureSize != INT_MAX);
174c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra}
175c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
176c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatrabool CameraSourceTimeLapse::computeCropRectangleOffset() {
177c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if ((mPictureWidth == mVideoWidth) && (mPictureHeight == mVideoHeight)) {
178c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        return false;
179c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    }
180c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
181c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    CHECK((mPictureWidth > mVideoWidth) && (mPictureHeight > mVideoHeight));
182c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
183c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    int32_t widthDifference = mPictureWidth - mVideoWidth;
184c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    int32_t heightDifference = mPictureHeight - mVideoHeight;
185c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
186c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    mCropRectStartX = widthDifference/2;
187c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    mCropRectStartY = heightDifference/2;
188c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
189c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    LOGV("setting crop rectangle offset to (%d, %d)", mCropRectStartX, mCropRectStartY);
190c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
191c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    return true;
192c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra}
193c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
19478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatravoid CameraSourceTimeLapse::signalBufferReturned(MediaBuffer* buffer) {
19578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    Mutex::Autolock autoLock(mQuickStopLock);
19678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    if (mQuickStop && (buffer == mLastReadBufferCopy)) {
19778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        buffer->setObserver(NULL);
19878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        buffer->release();
19978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    } else {
20078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        return CameraSource::signalBufferReturned(buffer);
20178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    }
20278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra}
20378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
20478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatravoid createMediaBufferCopy(const MediaBuffer& sourceBuffer, int64_t frameTime, MediaBuffer **newBuffer) {
20578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    size_t sourceSize = sourceBuffer.size();
20678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    void* sourcePointer = sourceBuffer.data();
20778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
20878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    (*newBuffer) = new MediaBuffer(sourceSize);
20978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    memcpy((*newBuffer)->data(), sourcePointer, sourceSize);
21078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
21178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    (*newBuffer)->meta_data()->setInt64(kKeyTime, frameTime);
21278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra}
21378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
21478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatravoid CameraSourceTimeLapse::fillLastReadBufferCopy(MediaBuffer& sourceBuffer) {
21578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    int64_t frameTime;
21678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    CHECK(sourceBuffer.meta_data()->findInt64(kKeyTime, &frameTime));
21778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    createMediaBufferCopy(sourceBuffer, frameTime, &mLastReadBufferCopy);
21878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mLastReadBufferCopy->add_ref();
21978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mLastReadBufferCopy->setObserver(this);
22078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra}
22178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
22278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatrastatus_t CameraSourceTimeLapse::read(
22378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        MediaBuffer **buffer, const ReadOptions *options) {
22478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    if (mLastReadBufferCopy == NULL) {
22578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        mLastReadStatus = CameraSource::read(buffer, options);
22678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
22778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // mQuickStop may have turned to true while read was blocked. Make a copy of
22878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // the buffer in that case.
22978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        Mutex::Autolock autoLock(mQuickStopLock);
23078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        if (mQuickStop && *buffer) {
23178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            fillLastReadBufferCopy(**buffer);
23278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        }
23378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        return mLastReadStatus;
23478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    } else {
23578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        (*buffer) = mLastReadBufferCopy;
23678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        (*buffer)->add_ref();
23778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        return mLastReadStatus;
23878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    }
23978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra}
24078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
24165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra// static
24265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid *CameraSourceTimeLapse::ThreadTimeLapseWrapper(void *me) {
24365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me);
24465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    source->threadTimeLapseEntry();
24565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    return NULL;
24665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
24765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
24865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::threadTimeLapseEntry() {
24978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    while (mStarted) {
25078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        {
25178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            Mutex::Autolock autoLock(mCameraIdleLock);
25278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            if (!mCameraIdle) {
25378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra                mCameraIdleCondition.wait(mCameraIdleLock);
25478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            }
25578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            CHECK(mCameraIdle);
2560aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra            mCameraIdle = false;
2570aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra        }
25878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
25978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // Even if mQuickStop == true we need to take one more picture
26078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // as a read() may be blocked, waiting for a frame to get available.
26178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // After this takePicture, if mQuickStop == true, we can safely exit
26278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // this thread as read() will make a copy of this last frame and keep
26378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // returning it in the quick stop mode.
26478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        Mutex::Autolock autoLock(mQuickStopLock);
26578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        CHECK_EQ(OK, mCamera->takePicture());
26678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        if (mQuickStop) {
26778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            LOGV("threadTimeLapseEntry: Exiting due to mQuickStop = true");
26878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            return;
26978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        }
27078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        mTakePictureCondition.waitRelative(mQuickStopLock,
27178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra                mTimeBetweenTimeLapseFrameCaptureUs * 1000);
27265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
27378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    LOGV("threadTimeLapseEntry: Exiting due to mStarted = false");
27465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
27565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
27665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::startCameraRecording() {
277c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (mUseStillCameraForTimeLapse) {
27865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        LOGV("start time lapse recording using still camera");
27965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
28065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        int64_t token = IPCThreadState::self()->clearCallingIdentity();
28165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        String8 s = mCamera->getParameters();
28265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        IPCThreadState::self()->restoreCallingIdentity(token);
28365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
28465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        CameraParameters params(s);
285c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        params.setPictureSize(mPictureWidth, mPictureHeight);
28665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        mCamera->setParameters(params.flatten());
2870aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra        mCameraIdle = true;
28878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        mStopWaitingForIdleCamera = false;
28965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
2903ee899e0466ecce107257beec04a2178939cf24eNipun Kwatra        // disable shutter sound and play the recording sound.
2913ee899e0466ecce107257beec04a2178939cf24eNipun Kwatra        mCamera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, 0, 0);
2923ee899e0466ecce107257beec04a2178939cf24eNipun Kwatra        mCamera->sendCommand(CAMERA_CMD_PLAY_RECORDING_SOUND, 0, 0);
2933ee899e0466ecce107257beec04a2178939cf24eNipun Kwatra
29465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        // create a thread which takes pictures in a loop
29565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        pthread_attr_t attr;
29665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        pthread_attr_init(&attr);
29765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
29865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
29965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        pthread_create(&mThreadTimeLapse, &attr, ThreadTimeLapseWrapper, this);
30065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        pthread_attr_destroy(&attr);
30165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    } else {
30265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        LOGV("start time lapse recording using video camera");
30365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        CHECK_EQ(OK, mCamera->startRecording());
30465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
30565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
30665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
30765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::stopCameraRecording() {
308c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (mUseStillCameraForTimeLapse) {
30965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        void *dummy;
31065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        pthread_join(mThreadTimeLapse, &dummy);
3113ee899e0466ecce107257beec04a2178939cf24eNipun Kwatra
31278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // Last takePicture may still be underway. Wait for the camera to get
31378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // idle.
31478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        Mutex::Autolock autoLock(mCameraIdleLock);
31578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        mStopWaitingForIdleCamera = true;
31678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        if (!mCameraIdle) {
31778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            mCameraIdleCondition.wait(mCameraIdleLock);
31878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        }
31978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        CHECK(mCameraIdle);
32078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        mCamera->setListener(NULL);
32178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
32278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // play the recording sound.
3233ee899e0466ecce107257beec04a2178939cf24eNipun Kwatra        mCamera->sendCommand(CAMERA_CMD_PLAY_RECORDING_SOUND, 0, 0);
32465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    } else {
32578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        mCamera->setListener(NULL);
32665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        mCamera->stopRecording();
32765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
32878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    if (mLastReadBufferCopy) {
32978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        mLastReadBufferCopy->release();
33078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        mLastReadBufferCopy = NULL;
33178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    }
33265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
33365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
33465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::releaseRecordingFrame(const sp<IMemory>& frame) {
335c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (!mUseStillCameraForTimeLapse) {
33665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        mCamera->releaseRecordingFrame(frame);
33765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
33865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
33965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
34065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatrasp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(const sp<IMemory> &source_data) {
34165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    size_t source_size = source_data->size();
34265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    void* source_pointer = source_data->pointer();
34365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
34465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    sp<MemoryHeapBase> newMemoryHeap = new MemoryHeapBase(source_size);
34565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    sp<MemoryBase> newMemory = new MemoryBase(newMemoryHeap, 0, source_size);
34665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    memcpy(newMemory->pointer(), source_pointer, source_size);
34765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    return newMemory;
34865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
34965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
350c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra// Allocates IMemory of final type MemoryBase with the given size.
351c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatrasp<IMemory> allocateIMemory(size_t size) {
352c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    sp<MemoryHeapBase> newMemoryHeap = new MemoryHeapBase(size);
353c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    sp<MemoryBase> newMemory = new MemoryBase(newMemoryHeap, 0, size);
354c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    return newMemory;
355c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra}
356c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
3570aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra// static
3580aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatravoid *CameraSourceTimeLapse::ThreadStartPreviewWrapper(void *me) {
3590aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me);
3600aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    source->threadStartPreview();
3610aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    return NULL;
3620aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra}
3630aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra
3640aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatravoid CameraSourceTimeLapse::threadStartPreview() {
3650aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    CHECK_EQ(OK, mCamera->startPreview());
36678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    Mutex::Autolock autoLock(mCameraIdleLock);
3670aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    mCameraIdle = true;
36878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mCameraIdleCondition.signal();
3690aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra}
3700aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra
3710aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatravoid CameraSourceTimeLapse::restartPreview() {
3720aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    // Start this in a different thread, so that the dataCallback can return
3730aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    LOGV("restartPreview");
3740aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    pthread_attr_t attr;
3750aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    pthread_attr_init(&attr);
3760aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3770aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra
3780aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    pthread_t threadPreview;
3790aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    pthread_create(&threadPreview, &attr, ThreadStartPreviewWrapper, this);
3800aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    pthread_attr_destroy(&attr);
3810aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra}
3820aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra
383c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatrasp<IMemory> CameraSourceTimeLapse::cropYUVImage(const sp<IMemory> &source_data) {
384c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    // find the YUV format
385c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    int32_t srcFormat;
386c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    CHECK(mMeta->findInt32(kKeyColorFormat, &srcFormat));
387c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    YUVImage::YUVFormat yuvFormat;
388c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (srcFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
389c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        yuvFormat = YUVImage::YUV420SemiPlanar;
390616715ab614ce25ea395a8e9a553a82637f1021dJames Dong    } else {
391616715ab614ce25ea395a8e9a553a82637f1021dJames Dong        CHECK_EQ(srcFormat, OMX_COLOR_FormatYUV420Planar);
392c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        yuvFormat = YUVImage::YUV420Planar;
393c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    }
394c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
395c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    // allocate memory for cropped image and setup a canvas using it.
396c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    sp<IMemory> croppedImageMemory = allocateIMemory(
397c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra            YUVImage::bufferSize(yuvFormat, mVideoWidth, mVideoHeight));
398c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    YUVImage yuvImageCropped(yuvFormat,
399c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra            mVideoWidth, mVideoHeight,
400c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra            (uint8_t *)croppedImageMemory->pointer());
401c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    YUVCanvas yuvCanvasCrop(yuvImageCropped);
402c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
403c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    YUVImage yuvImageSource(yuvFormat,
404c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra            mPictureWidth, mPictureHeight,
405c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra            (uint8_t *)source_data->pointer());
406c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    yuvCanvasCrop.CopyImageRect(
407c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra            Rect(mCropRectStartX, mCropRectStartY,
408c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra                mCropRectStartX + mVideoWidth,
409c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra                mCropRectStartY + mVideoHeight),
410c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra            0, 0,
411c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra            yuvImageSource);
412c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
413c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    return croppedImageMemory;
414c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra}
415c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
41665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::dataCallback(int32_t msgType, const sp<IMemory> &data) {
417c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (msgType == CAMERA_MSG_COMPRESSED_IMAGE) {
4180aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra        // takePicture will complete after this callback, so restart preview.
4190aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra        restartPreview();
420c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        return;
4210aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra    }
422c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (msgType != CAMERA_MSG_RAW_IMAGE) {
42365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return;
42465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
42565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
42665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    LOGV("dataCallback for timelapse still frame");
42765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    CHECK_EQ(true, mUseStillCameraForTimeLapse);
42865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
42965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    int64_t timestampUs;
43065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    if (mNumFramesReceived == 0) {
43165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        timestampUs = mStartTimeUs;
43265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    } else {
43365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
43465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
435c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra
436c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (mNeedCropping) {
437c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        sp<IMemory> croppedImageData = cropYUVImage(data);
438c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        dataCallbackTimestamp(timestampUs, msgType, croppedImageData);
439c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    } else {
440c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        sp<IMemory> dataCopy = createIMemoryCopy(data);
441c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        dataCallbackTimestamp(timestampUs, msgType, dataCopy);
442c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    }
44365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
44465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
44565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatrabool CameraSourceTimeLapse::skipCurrentFrame(int64_t timestampUs) {
446c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (mSkipCurrentFrame) {
44765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        mSkipCurrentFrame = false;
44865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return true;
44965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    } else {
45065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return false;
45165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
45265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
45365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
45465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatrabool CameraSourceTimeLapse::skipFrameAndModifyTimeStamp(int64_t *timestampUs) {
455c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (!mUseStillCameraForTimeLapse) {
456c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra        if (mLastTimeLapseFrameRealTimestampUs == 0) {
45765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // First time lapse frame. Initialize mLastTimeLapseFrameRealTimestampUs
45865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // to current time (timestampUs) and save frame data.
45965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            LOGV("dataCallbackTimestamp timelapse: initial frame");
46065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
46165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            mLastTimeLapseFrameRealTimestampUs = *timestampUs;
46278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            return false;
46378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        }
46478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
46578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        {
46678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            Mutex::Autolock autoLock(mQuickStopLock);
46778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
46878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            // mForceRead may be set to true by startQuickReadReturns(). In that
46978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            // case don't skip this frame.
47078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            if (mForceRead) {
47178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra                LOGV("dataCallbackTimestamp timelapse: forced read");
47278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra                mForceRead = false;
47378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra                *timestampUs = mLastFrameTimestampUs;
47478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra                return false;
47578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            }
47678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        }
47778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
47878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        if (*timestampUs <
47965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra                (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenTimeLapseFrameCaptureUs)) {
48065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // Skip all frames from last encoded frame until
48165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // sufficient time (mTimeBetweenTimeLapseFrameCaptureUs) has passed.
48265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // Tell the camera to release its recording frame and return.
48365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            LOGV("dataCallbackTimestamp timelapse: skipping intermediate frame");
48465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            return true;
48565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        } else {
48665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // Desired frame has arrived after mTimeBetweenTimeLapseFrameCaptureUs time:
48765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // - Reset mLastTimeLapseFrameRealTimestampUs to current time.
48865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // - Artificially modify timestampUs to be one frame time (1/framerate) ahead
48965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            // of the last encoded frame's time stamp.
49065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            LOGV("dataCallbackTimestamp timelapse: got timelapse frame");
49165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
49265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            mLastTimeLapseFrameRealTimestampUs = *timestampUs;
49365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
49478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            return false;
49565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        }
49665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
49765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    return false;
49865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
49965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
50065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
50165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            const sp<IMemory> &data) {
502c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (!mUseStillCameraForTimeLapse) {
50365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        mSkipCurrentFrame = skipFrameAndModifyTimeStamp(&timestampUs);
50478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    } else {
50578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        Mutex::Autolock autoLock(mCameraIdleLock);
50678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // If we are using the still camera and stop() has been called, it may
50778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // be waiting for the camera to get idle. In that case return
50878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // immediately. Calling CameraSource::dataCallbackTimestamp() will lead
50978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // to a deadlock since it tries to access CameraSource::mLock which in
51078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // this case is held by CameraSource::stop() currently waiting for the
51178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // camera to get idle. And camera will not get idle until this call
51278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        // returns.
51378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        if (mStopWaitingForIdleCamera) {
51478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            return;
51578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        }
51665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
51765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    CameraSource::dataCallbackTimestamp(timestampUs, msgType, data);
51865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
51965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
52065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}  // namespace android
521