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(×tampUs); 34565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } 34665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra CameraSource::dataCallbackTimestamp(timestampUs, msgType, data); 34765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 34865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 34965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} // namespace android 350