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
17a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h>
18a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
1965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra//#define LOG_NDEBUG 0
2065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#define LOG_TAG "CameraSourceTimeLapse"
2165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
2265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <binder/IPCThreadState.h>
2365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <binder/MemoryBase.h>
2465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <binder/MemoryHeapBase.h>
25f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h>
2665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <media/stagefright/CameraSource.h>
2765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <media/stagefright/CameraSourceTimeLapse.h>
2865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <media/stagefright/MetaData.h>
2965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <camera/Camera.h>
3065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <camera/CameraParameters.h>
3165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <utils/String8.h>
3240e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra#include <utils/Vector.h>
3365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
3465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatranamespace android {
3565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
3665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra// static
3754ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera(
38d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala        const sp<hardware::ICamera> &camera,
394ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        const sp<ICameraRecordingProxy> &proxy,
4054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t cameraId,
41ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        const String16& clientName,
42ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        uid_t clientUid,
4398a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen        pid_t clientPid,
4454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        Size videoSize,
4554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t videoFrameRate,
4699617adda9bc46c43f511f0940bc735c73de61deMathias Agopian        const sp<IGraphicBufferProducer>& surface,
479c7f845780d62ea09469a8dac7117cc01adfea5cLajos Molnar        int64_t timeBetweenFrameCaptureUs,
489c7f845780d62ea09469a8dac7117cc01adfea5cLajos Molnar        bool storeMetaDataInVideoBuffers) {
4954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
5054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraSourceTimeLapse *source = new
514ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li            CameraSourceTimeLapse(camera, proxy, cameraId,
5298a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen                clientName, clientUid, clientPid,
5354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                videoSize, videoFrameRate, surface,
549c7f845780d62ea09469a8dac7117cc01adfea5cLajos Molnar                timeBetweenFrameCaptureUs,
559c7f845780d62ea09469a8dac7117cc01adfea5cLajos Molnar                storeMetaDataInVideoBuffers);
5654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
5754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (source != NULL) {
5854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (source->initCheck() != OK) {
5954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            delete source;
6054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return NULL;
6154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
6265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
6354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return source;
6465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
6565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
6654ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSourceTimeLapse::CameraSourceTimeLapse(
67d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala        const sp<hardware::ICamera>& camera,
684ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        const sp<ICameraRecordingProxy>& proxy,
6954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t cameraId,
70ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        const String16& clientName,
71ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        uid_t clientUid,
7298a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen        pid_t clientPid,
7354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        Size videoSize,
7454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t videoFrameRate,
7599617adda9bc46c43f511f0940bc735c73de61deMathias Agopian        const sp<IGraphicBufferProducer>& surface,
769c7f845780d62ea09469a8dac7117cc01adfea5cLajos Molnar        int64_t timeBetweenFrameCaptureUs,
779c7f845780d62ea09469a8dac7117cc01adfea5cLajos Molnar        bool storeMetaDataInVideoBuffers)
7898a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen      : CameraSource(camera, proxy, cameraId, clientName, clientUid, clientPid,
799c7f845780d62ea09469a8dac7117cc01adfea5cLajos Molnar                videoSize, videoFrameRate, surface,
809c7f845780d62ea09469a8dac7117cc01adfea5cLajos Molnar                storeMetaDataInVideoBuffers),
8165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mTimeBetweenTimeLapseVideoFramesUs(1E6/videoFrameRate),
8265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mLastTimeLapseFrameRealTimestampUs(0),
8365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mSkipCurrentFrame(false) {
8465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
85e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong    mTimeBetweenFrameCaptureUs = timeBetweenFrameCaptureUs;
86a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGD("starting time lapse mode: %" PRId64 " us",
87e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong        mTimeBetweenFrameCaptureUs);
883cecf640c4daf2df616b278bd9986018c8182908James Dong
8954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoWidth = videoSize.width;
9054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoHeight = videoSize.height;
91155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra
929bb976e1c78048081cf9df4d8a1db67311413e5bRobert Shih    if (OK == mInitCheck && !trySettingVideoSize(videoSize.width, videoSize.height)) {
939bb976e1c78048081cf9df4d8a1db67311413e5bRobert Shih        releaseCamera();
943cecf640c4daf2df616b278bd9986018c8182908James Dong        mInitCheck = NO_INIT;
9565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
9678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
9778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    // Initialize quick stop variables.
9878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mQuickStop = false;
9978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mForceRead = false;
10078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mLastReadBufferCopy = NULL;
10178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mStopWaitingForIdleCamera = false;
10265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
10365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
10465e7e6facda89927cb26594b3b65ae81b3235ebcNipun KwatraCameraSourceTimeLapse::~CameraSourceTimeLapse() {
105b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong    if (mLastReadBufferCopy) {
106b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong        mLastReadBufferCopy->release();
107b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong        mLastReadBufferCopy = NULL;
108b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong    }
10965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
11065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
11178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatravoid CameraSourceTimeLapse::startQuickReadReturns() {
1123856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startQuickReadReturns");
11378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    Mutex::Autolock autoLock(mQuickStopLock);
11478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
11578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    // Enable quick stop mode.
11678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mQuickStop = true;
11778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
1183cecf640c4daf2df616b278bd9986018c8182908James Dong    // Force dataCallbackTimestamp() coming from the video camera to
1193cecf640c4daf2df616b278bd9986018c8182908James Dong    // not skip the next frame as we want read() to get a get a frame
1203cecf640c4daf2df616b278bd9986018c8182908James Dong    // right away.
1213cecf640c4daf2df616b278bd9986018c8182908James Dong    mForceRead = true;
12278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra}
12378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
1243cecf640c4daf2df616b278bd9986018c8182908James Dongbool CameraSourceTimeLapse::trySettingVideoSize(
1253cecf640c4daf2df616b278bd9986018c8182908James Dong        int32_t width, int32_t height) {
1263cecf640c4daf2df616b278bd9986018c8182908James Dong
1273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("trySettingVideoSize");
128155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    int64_t token = IPCThreadState::self()->clearCallingIdentity();
129155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    String8 s = mCamera->getParameters();
130155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra
131155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    CameraParameters params(s);
132155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    Vector<Size> supportedSizes;
13328934a90e168291f6c77c56e8a05f272e5151bbdJames Dong    params.getSupportedVideoSizes(supportedSizes);
13428934a90e168291f6c77c56e8a05f272e5151bbdJames Dong    bool videoOutputSupported = false;
13528934a90e168291f6c77c56e8a05f272e5151bbdJames Dong    if (supportedSizes.size() == 0) {
13628934a90e168291f6c77c56e8a05f272e5151bbdJames Dong        params.getSupportedPreviewSizes(supportedSizes);
13728934a90e168291f6c77c56e8a05f272e5151bbdJames Dong    } else {
13828934a90e168291f6c77c56e8a05f272e5151bbdJames Dong        videoOutputSupported = true;
13928934a90e168291f6c77c56e8a05f272e5151bbdJames Dong    }
140155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra
14128934a90e168291f6c77c56e8a05f272e5151bbdJames Dong    bool videoSizeSupported = false;
1423ab368e0810d894dcbc0971350c095049478a055Mark Salyzyn    for (size_t i = 0; i < supportedSizes.size(); ++i) {
143155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra        int32_t pictureWidth = supportedSizes[i].width;
144155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra        int32_t pictureHeight = supportedSizes[i].height;
145155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra
146155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra        if ((pictureWidth == width) && (pictureHeight == height)) {
14728934a90e168291f6c77c56e8a05f272e5151bbdJames Dong            videoSizeSupported = true;
148155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra        }
149155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    }
150155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra
151ba29002c7aee13c068049037cd14bba6a244da6bJames Dong    bool isSuccessful = false;
15228934a90e168291f6c77c56e8a05f272e5151bbdJames Dong    if (videoSizeSupported) {
1533856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Video size (%d, %d) is supported", width, height);
15428934a90e168291f6c77c56e8a05f272e5151bbdJames Dong        if (videoOutputSupported) {
15528934a90e168291f6c77c56e8a05f272e5151bbdJames Dong            params.setVideoSize(width, height);
15628934a90e168291f6c77c56e8a05f272e5151bbdJames Dong        } else {
15728934a90e168291f6c77c56e8a05f272e5151bbdJames Dong            params.setPreviewSize(width, height);
15828934a90e168291f6c77c56e8a05f272e5151bbdJames Dong        }
159ba29002c7aee13c068049037cd14bba6a244da6bJames Dong        if (mCamera->setParameters(params.flatten()) == OK) {
160ba29002c7aee13c068049037cd14bba6a244da6bJames Dong            isSuccessful = true;
161ba29002c7aee13c068049037cd14bba6a244da6bJames Dong        } else {
16229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Failed to set preview size to %dx%d", width, height);
163ba29002c7aee13c068049037cd14bba6a244da6bJames Dong            isSuccessful = false;
164ba29002c7aee13c068049037cd14bba6a244da6bJames Dong        }
165155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra    }
166155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra
167ba29002c7aee13c068049037cd14bba6a244da6bJames Dong    IPCThreadState::self()->restoreCallingIdentity(token);
168ba29002c7aee13c068049037cd14bba6a244da6bJames Dong    return isSuccessful;
169155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra}
170155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra
17178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatravoid CameraSourceTimeLapse::signalBufferReturned(MediaBuffer* buffer) {
1723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("signalBufferReturned");
17378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    Mutex::Autolock autoLock(mQuickStopLock);
17478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    if (mQuickStop && (buffer == mLastReadBufferCopy)) {
17578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        buffer->setObserver(NULL);
17678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        buffer->release();
17778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    } else {
17878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        return CameraSource::signalBufferReturned(buffer);
17978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    }
18078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra}
18178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
1823cecf640c4daf2df616b278bd9986018c8182908James Dongvoid createMediaBufferCopy(
1833cecf640c4daf2df616b278bd9986018c8182908James Dong        const MediaBuffer& sourceBuffer,
1843cecf640c4daf2df616b278bd9986018c8182908James Dong        int64_t frameTime,
1853cecf640c4daf2df616b278bd9986018c8182908James Dong        MediaBuffer **newBuffer) {
1863cecf640c4daf2df616b278bd9986018c8182908James Dong
1873856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("createMediaBufferCopy");
18878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    size_t sourceSize = sourceBuffer.size();
18978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    void* sourcePointer = sourceBuffer.data();
19078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
19178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    (*newBuffer) = new MediaBuffer(sourceSize);
19278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    memcpy((*newBuffer)->data(), sourcePointer, sourceSize);
19378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
19478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    (*newBuffer)->meta_data()->setInt64(kKeyTime, frameTime);
19578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra}
19678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
19778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatravoid CameraSourceTimeLapse::fillLastReadBufferCopy(MediaBuffer& sourceBuffer) {
1983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("fillLastReadBufferCopy");
19978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    int64_t frameTime;
20078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    CHECK(sourceBuffer.meta_data()->findInt64(kKeyTime, &frameTime));
20178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    createMediaBufferCopy(sourceBuffer, frameTime, &mLastReadBufferCopy);
20278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mLastReadBufferCopy->add_ref();
20378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mLastReadBufferCopy->setObserver(this);
20478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra}
20578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
20678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatrastatus_t CameraSourceTimeLapse::read(
20778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        MediaBuffer **buffer, const ReadOptions *options) {
2083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("read");
20978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    if (mLastReadBufferCopy == NULL) {
21078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        mLastReadStatus = CameraSource::read(buffer, options);
21178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
2123cecf640c4daf2df616b278bd9986018c8182908James Dong        // mQuickStop may have turned to true while read was blocked.
2133cecf640c4daf2df616b278bd9986018c8182908James Dong        // Make a copy of the buffer in that case.
21478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        Mutex::Autolock autoLock(mQuickStopLock);
21578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        if (mQuickStop && *buffer) {
21678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            fillLastReadBufferCopy(**buffer);
21778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        }
21878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        return mLastReadStatus;
21978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    } else {
22078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        (*buffer) = mLastReadBufferCopy;
22178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        (*buffer)->add_ref();
22278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra        return mLastReadStatus;
22378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    }
22478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra}
22578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
2263cecf640c4daf2df616b278bd9986018c8182908James Dongsp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(
2273cecf640c4daf2df616b278bd9986018c8182908James Dong        const sp<IMemory> &source_data) {
22865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
2293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("createIMemoryCopy");
23065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    size_t source_size = source_data->size();
23165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    void* source_pointer = source_data->pointer();
23265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
23365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    sp<MemoryHeapBase> newMemoryHeap = new MemoryHeapBase(source_size);
23465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    sp<MemoryBase> newMemory = new MemoryBase(newMemoryHeap, 0, source_size);
23565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    memcpy(newMemory->pointer(), source_pointer, source_size);
23665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    return newMemory;
23765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
23865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
23984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberbool CameraSourceTimeLapse::skipCurrentFrame(int64_t /* timestampUs */) {
2403856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("skipCurrentFrame");
241c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra    if (mSkipCurrentFrame) {
24265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        mSkipCurrentFrame = false;
24365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return true;
24465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    } else {
24565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return false;
24665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
24765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
24865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
24965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatrabool CameraSourceTimeLapse::skipFrameAndModifyTimeStamp(int64_t *timestampUs) {
2503856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("skipFrameAndModifyTimeStamp");
2513cecf640c4daf2df616b278bd9986018c8182908James Dong    if (mLastTimeLapseFrameRealTimestampUs == 0) {
2523cecf640c4daf2df616b278bd9986018c8182908James Dong        // First time lapse frame. Initialize mLastTimeLapseFrameRealTimestampUs
2533cecf640c4daf2df616b278bd9986018c8182908James Dong        // to current time (timestampUs) and save frame data.
2543856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("dataCallbackTimestamp timelapse: initial frame");
25565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
2563cecf640c4daf2df616b278bd9986018c8182908James Dong        mLastTimeLapseFrameRealTimestampUs = *timestampUs;
2573cecf640c4daf2df616b278bd9986018c8182908James Dong        return false;
2583cecf640c4daf2df616b278bd9986018c8182908James Dong    }
25978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
2603cecf640c4daf2df616b278bd9986018c8182908James Dong    {
2613cecf640c4daf2df616b278bd9986018c8182908James Dong        Mutex::Autolock autoLock(mQuickStopLock);
26278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra
2633cecf640c4daf2df616b278bd9986018c8182908James Dong        // mForceRead may be set to true by startQuickReadReturns(). In that
2643cecf640c4daf2df616b278bd9986018c8182908James Dong        // case don't skip this frame.
2653cecf640c4daf2df616b278bd9986018c8182908James Dong        if (mForceRead) {
2663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("dataCallbackTimestamp timelapse: forced read");
2673cecf640c4daf2df616b278bd9986018c8182908James Dong            mForceRead = false;
2683cecf640c4daf2df616b278bd9986018c8182908James Dong            *timestampUs =
2693cecf640c4daf2df616b278bd9986018c8182908James Dong                mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
27093594b5aa16dbbb0b196f6e181a8ca099d7ab62bJames Dong
27193594b5aa16dbbb0b196f6e181a8ca099d7ab62bJames Dong            // Really make sure that this video recording frame will not be dropped.
27293594b5aa16dbbb0b196f6e181a8ca099d7ab62bJames Dong            if (*timestampUs < mStartTimeUs) {
273a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                ALOGI("set timestampUs to start time stamp %" PRId64 " us", mStartTimeUs);
27493594b5aa16dbbb0b196f6e181a8ca099d7ab62bJames Dong                *timestampUs = mStartTimeUs;
27593594b5aa16dbbb0b196f6e181a8ca099d7ab62bJames Dong            }
27678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra            return false;
27765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        }
27865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
2793cecf640c4daf2df616b278bd9986018c8182908James Dong
2803cecf640c4daf2df616b278bd9986018c8182908James Dong    // Workaround to bypass the first 2 input frames for skipping.
2813cecf640c4daf2df616b278bd9986018c8182908James Dong    // The first 2 output frames from the encoder are: decoder specific info and
2823cecf640c4daf2df616b278bd9986018c8182908James Dong    // the compressed video frame data for the first input video frame.
2833cecf640c4daf2df616b278bd9986018c8182908James Dong    if (mNumFramesEncoded >= 1 && *timestampUs <
284e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong        (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenFrameCaptureUs)) {
2853cecf640c4daf2df616b278bd9986018c8182908James Dong        // Skip all frames from last encoded frame until
286e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong        // sufficient time (mTimeBetweenFrameCaptureUs) has passed.
2873cecf640c4daf2df616b278bd9986018c8182908James Dong        // Tell the camera to release its recording frame and return.
2883856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("dataCallbackTimestamp timelapse: skipping intermediate frame");
2893cecf640c4daf2df616b278bd9986018c8182908James Dong        return true;
2903cecf640c4daf2df616b278bd9986018c8182908James Dong    } else {
291e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong        // Desired frame has arrived after mTimeBetweenFrameCaptureUs time:
2923cecf640c4daf2df616b278bd9986018c8182908James Dong        // - Reset mLastTimeLapseFrameRealTimestampUs to current time.
2933cecf640c4daf2df616b278bd9986018c8182908James Dong        // - Artificially modify timestampUs to be one frame time (1/framerate) ahead
2943cecf640c4daf2df616b278bd9986018c8182908James Dong        // of the last encoded frame's time stamp.
2953856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("dataCallbackTimestamp timelapse: got timelapse frame");
2963cecf640c4daf2df616b278bd9986018c8182908James Dong
2973cecf640c4daf2df616b278bd9986018c8182908James Dong        mLastTimeLapseFrameRealTimestampUs = *timestampUs;
2983cecf640c4daf2df616b278bd9986018c8182908James Dong        *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
2993cecf640c4daf2df616b278bd9986018c8182908James Dong        return false;
3003cecf640c4daf2df616b278bd9986018c8182908James Dong    }
30165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    return false;
30265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
30365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
30465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
30565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra            const sp<IMemory> &data) {
3063856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("dataCallbackTimestamp");
3073cecf640c4daf2df616b278bd9986018c8182908James Dong    mSkipCurrentFrame = skipFrameAndModifyTimeStamp(&timestampUs);
30865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    CameraSource::dataCallbackTimestamp(timestampUs, msgType, data);
30965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
31065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
3112d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chenvoid CameraSourceTimeLapse::recordingFrameHandleCallbackTimestamp(int64_t timestampUs,
3122d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen            native_handle_t* handle) {
3132d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    ALOGV("recordingFrameHandleCallbackTimestamp");
3142d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    mSkipCurrentFrame = skipFrameAndModifyTimeStamp(&timestampUs);
3152d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    CameraSource::recordingFrameHandleCallbackTimestamp(timestampUs, handle);
3162d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen}
3172d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen
3188fc3c670fff26cb21d1e16dbfcbc4410d7758574Chien-Yu Chenvoid CameraSourceTimeLapse::processBufferQueueFrame(BufferItem& buffer) {
3198fc3c670fff26cb21d1e16dbfcbc4410d7758574Chien-Yu Chen    ALOGV("processBufferQueueFrame");
3208fc3c670fff26cb21d1e16dbfcbc4410d7758574Chien-Yu Chen    int64_t timestampUs = buffer.mTimestamp / 1000;
3218fc3c670fff26cb21d1e16dbfcbc4410d7758574Chien-Yu Chen    mSkipCurrentFrame = skipFrameAndModifyTimeStamp(&timestampUs);
3228fc3c670fff26cb21d1e16dbfcbc4410d7758574Chien-Yu Chen    buffer.mTimestamp = timestampUs * 1000;
3238fc3c670fff26cb21d1e16dbfcbc4410d7758574Chien-Yu Chen    CameraSource::processBufferQueueFrame(buffer);
3248fc3c670fff26cb21d1e16dbfcbc4410d7758574Chien-Yu Chen}
3258fc3c670fff26cb21d1e16dbfcbc4410d7758574Chien-Yu Chen
32665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}  // namespace android
327