CameraSourceTimeLapse.cpp revision 40e2f3f9b41f44bdb59f7708a421b87f169a6ede
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" 3565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 3665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatranamespace android { 3765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 3865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra// static 3965e7e6facda89927cb26594b3b65ae81b3235ebcNipun KwatraCameraSourceTimeLapse *CameraSourceTimeLapse::Create(bool useStillCameraForTimeLapse, 4065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra int64_t timeBetweenTimeLapseFrameCaptureUs, 41e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra int32_t width, int32_t height, 4265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra int32_t videoFrameRate) { 4365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra sp<Camera> camera = Camera::connect(0); 4465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 4565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra if (camera.get() == NULL) { 4665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra return NULL; 4765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } 4865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 4965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra return new CameraSourceTimeLapse(camera, useStillCameraForTimeLapse, 50e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra timeBetweenTimeLapseFrameCaptureUs, width, height, videoFrameRate); 5165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 5265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 5365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra// static 5465e7e6facda89927cb26594b3b65ae81b3235ebcNipun KwatraCameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera(const sp<Camera> &camera, 5565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra bool useStillCameraForTimeLapse, 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 6365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra return new CameraSourceTimeLapse(camera, useStillCameraForTimeLapse, 64e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra timeBetweenTimeLapseFrameCaptureUs, width, height, videoFrameRate); 6565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 6665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 6765e7e6facda89927cb26594b3b65ae81b3235ebcNipun KwatraCameraSourceTimeLapse::CameraSourceTimeLapse(const sp<Camera> &camera, 6865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra bool useStillCameraForTimeLapse, 6965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra int64_t timeBetweenTimeLapseFrameCaptureUs, 70e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra int32_t width, int32_t height, 7165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra int32_t videoFrameRate) 7265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra : CameraSource(camera), 7365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mUseStillCameraForTimeLapse(useStillCameraForTimeLapse), 7465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mTimeBetweenTimeLapseFrameCaptureUs(timeBetweenTimeLapseFrameCaptureUs), 7565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mTimeBetweenTimeLapseVideoFramesUs(1E6/videoFrameRate), 7665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mLastTimeLapseFrameRealTimestampUs(0), 7765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mSkipCurrentFrame(false) { 7865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 7965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra LOGV("starting time lapse mode"); 80c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra mVideoWidth = width; 81c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra mVideoHeight = height; 82c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra if (mUseStillCameraForTimeLapse) { 8340e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra CHECK(setPictureSizeToClosestSupported(width, height)); 84c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra mNeedCropping = computeCropRectangleOffset(); 8565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mMeta->setInt32(kKeyWidth, width); 8665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mMeta->setInt32(kKeyHeight, height); 8765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } 8865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 8965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 9065e7e6facda89927cb26594b3b65ae81b3235ebcNipun KwatraCameraSourceTimeLapse::~CameraSourceTimeLapse() { 9165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 9265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 9340e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatrabool CameraSourceTimeLapse::setPictureSizeToClosestSupported(int32_t width, int32_t height) { 9440e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra int64_t token = IPCThreadState::self()->clearCallingIdentity(); 9540e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra String8 s = mCamera->getParameters(); 9640e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra IPCThreadState::self()->restoreCallingIdentity(token); 9740e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra 9840e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra CameraParameters params(s); 9940e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra Vector<Size> supportedSizes; 10040e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra params.getSupportedPictureSizes(supportedSizes); 10140e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra 10240e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra int32_t minPictureSize = INT_MAX; 10340e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra for (uint32_t i = 0; i < supportedSizes.size(); ++i) { 10440e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra int32_t pictureWidth = supportedSizes[i].width; 10540e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra int32_t pictureHeight = supportedSizes[i].height; 10640e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra 10740e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra if ((pictureWidth >= width) && (pictureHeight >= height)) { 10840e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra int32_t pictureSize = pictureWidth*pictureHeight; 10940e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra if (pictureSize < minPictureSize) { 11040e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra minPictureSize = pictureSize; 11140e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra mPictureWidth = pictureWidth; 11240e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra mPictureHeight = pictureHeight; 11340e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra } 11440e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra } 11540e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra } 11640e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra LOGV("Picture size = (%d, %d)", mPictureWidth, mPictureHeight); 11740e2f3f9b41f44bdb59f7708a421b87f169a6edeNipun Kwatra return (minPictureSize != INT_MAX); 118c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra} 119c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra 120c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatrabool CameraSourceTimeLapse::computeCropRectangleOffset() { 121c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra if ((mPictureWidth == mVideoWidth) && (mPictureHeight == mVideoHeight)) { 122c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra return false; 123c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra } 124c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra 125c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra CHECK((mPictureWidth > mVideoWidth) && (mPictureHeight > mVideoHeight)); 126c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra 127c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra int32_t widthDifference = mPictureWidth - mVideoWidth; 128c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra int32_t heightDifference = mPictureHeight - mVideoHeight; 129c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra 130c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra mCropRectStartX = widthDifference/2; 131c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra mCropRectStartY = heightDifference/2; 132c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra 133c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra LOGV("setting crop rectangle offset to (%d, %d)", mCropRectStartX, mCropRectStartY); 134c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra 135c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra return true; 136c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra} 137c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra 13865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra// static 13965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid *CameraSourceTimeLapse::ThreadTimeLapseWrapper(void *me) { 14065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me); 14165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra source->threadTimeLapseEntry(); 14265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra return NULL; 14365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 14465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 14565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::threadTimeLapseEntry() { 14665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra while(mStarted) { 147c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra if (mCameraIdle) { 1480aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra LOGV("threadTimeLapseEntry: taking picture"); 1490aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra CHECK_EQ(OK, mCamera->takePicture()); 1500aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra mCameraIdle = false; 1510aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra sleep(mTimeBetweenTimeLapseFrameCaptureUs/1E6); 1520aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra } else { 1530aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra LOGV("threadTimeLapseEntry: camera busy with old takePicture. Sleeping a little."); 1540aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra sleep(.01); 1550aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra } 15665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } 15765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 15865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 15965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::startCameraRecording() { 160c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra if (mUseStillCameraForTimeLapse) { 16165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra LOGV("start time lapse recording using still camera"); 16265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 16365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra int64_t token = IPCThreadState::self()->clearCallingIdentity(); 16465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra String8 s = mCamera->getParameters(); 16565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra IPCThreadState::self()->restoreCallingIdentity(token); 16665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 16765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra CameraParameters params(s); 168c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra params.setPictureSize(mPictureWidth, mPictureHeight); 16965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mCamera->setParameters(params.flatten()); 1700aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra mCameraIdle = true; 17165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 17265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // create a thread which takes pictures in a loop 17365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra pthread_attr_t attr; 17465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra pthread_attr_init(&attr); 17565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 17665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 17765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra pthread_create(&mThreadTimeLapse, &attr, ThreadTimeLapseWrapper, this); 17865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra pthread_attr_destroy(&attr); 17965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } else { 18065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra LOGV("start time lapse recording using video camera"); 18165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra CHECK_EQ(OK, mCamera->startRecording()); 18265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } 18365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 18465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 18565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::stopCameraRecording() { 186c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra if (mUseStillCameraForTimeLapse) { 18765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra void *dummy; 18865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra pthread_join(mThreadTimeLapse, &dummy); 18965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } else { 19065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mCamera->stopRecording(); 19165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } 19265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 19365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 19465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::releaseRecordingFrame(const sp<IMemory>& frame) { 195c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra if (!mUseStillCameraForTimeLapse) { 19665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mCamera->releaseRecordingFrame(frame); 19765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } 19865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 19965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 20065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatrasp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(const sp<IMemory> &source_data) { 20165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra size_t source_size = source_data->size(); 20265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra void* source_pointer = source_data->pointer(); 20365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 20465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra sp<MemoryHeapBase> newMemoryHeap = new MemoryHeapBase(source_size); 20565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra sp<MemoryBase> newMemory = new MemoryBase(newMemoryHeap, 0, source_size); 20665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra memcpy(newMemory->pointer(), source_pointer, source_size); 20765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra return newMemory; 20865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 20965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 210c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra// Allocates IMemory of final type MemoryBase with the given size. 211c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatrasp<IMemory> allocateIMemory(size_t size) { 212c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra sp<MemoryHeapBase> newMemoryHeap = new MemoryHeapBase(size); 213c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra sp<MemoryBase> newMemory = new MemoryBase(newMemoryHeap, 0, size); 214c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra return newMemory; 215c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra} 216c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra 2170aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra// static 2180aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatravoid *CameraSourceTimeLapse::ThreadStartPreviewWrapper(void *me) { 2190aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me); 2200aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra source->threadStartPreview(); 2210aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra return NULL; 2220aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra} 2230aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra 2240aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatravoid CameraSourceTimeLapse::threadStartPreview() { 2250aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra CHECK_EQ(OK, mCamera->startPreview()); 2260aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra mCameraIdle = true; 2270aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra} 2280aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra 2290aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatravoid CameraSourceTimeLapse::restartPreview() { 2300aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra // Start this in a different thread, so that the dataCallback can return 2310aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra LOGV("restartPreview"); 2320aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra pthread_attr_t attr; 2330aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra pthread_attr_init(&attr); 2340aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 2350aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra 2360aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra pthread_t threadPreview; 2370aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra pthread_create(&threadPreview, &attr, ThreadStartPreviewWrapper, this); 2380aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra pthread_attr_destroy(&attr); 2390aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra} 2400aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra 241c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatrasp<IMemory> CameraSourceTimeLapse::cropYUVImage(const sp<IMemory> &source_data) { 242c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra // find the YUV format 243c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra int32_t srcFormat; 244c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra CHECK(mMeta->findInt32(kKeyColorFormat, &srcFormat)); 245c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra YUVImage::YUVFormat yuvFormat; 246c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra if (srcFormat == OMX_COLOR_FormatYUV420SemiPlanar) { 247c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra yuvFormat = YUVImage::YUV420SemiPlanar; 248c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra } else if (srcFormat == OMX_COLOR_FormatYUV420Planar) { 249c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra yuvFormat = YUVImage::YUV420Planar; 250c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra } 251c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra 252c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra // allocate memory for cropped image and setup a canvas using it. 253c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra sp<IMemory> croppedImageMemory = allocateIMemory( 254c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra YUVImage::bufferSize(yuvFormat, mVideoWidth, mVideoHeight)); 255c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra YUVImage yuvImageCropped(yuvFormat, 256c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra mVideoWidth, mVideoHeight, 257c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra (uint8_t *)croppedImageMemory->pointer()); 258c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra YUVCanvas yuvCanvasCrop(yuvImageCropped); 259c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra 260c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra YUVImage yuvImageSource(yuvFormat, 261c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra mPictureWidth, mPictureHeight, 262c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra (uint8_t *)source_data->pointer()); 263c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra yuvCanvasCrop.CopyImageRect( 264c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra Rect(mCropRectStartX, mCropRectStartY, 265c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra mCropRectStartX + mVideoWidth, 266c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra mCropRectStartY + mVideoHeight), 267c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra 0, 0, 268c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra yuvImageSource); 269c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra 270c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra return croppedImageMemory; 271c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra} 272c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra 27365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::dataCallback(int32_t msgType, const sp<IMemory> &data) { 274c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra if (msgType == CAMERA_MSG_COMPRESSED_IMAGE) { 2750aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra // takePicture will complete after this callback, so restart preview. 2760aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra restartPreview(); 277c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra return; 2780aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra } 279c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra if (msgType != CAMERA_MSG_RAW_IMAGE) { 28065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra return; 28165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } 28265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 28365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra LOGV("dataCallback for timelapse still frame"); 28465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra CHECK_EQ(true, mUseStillCameraForTimeLapse); 28565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 28665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra int64_t timestampUs; 28765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra if (mNumFramesReceived == 0) { 28865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra timestampUs = mStartTimeUs; 28965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } else { 29065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs; 29165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } 292c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra 293c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra if (mNeedCropping) { 294c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra sp<IMemory> croppedImageData = cropYUVImage(data); 295c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra dataCallbackTimestamp(timestampUs, msgType, croppedImageData); 296c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra } else { 297c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra sp<IMemory> dataCopy = createIMemoryCopy(data); 298c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra dataCallbackTimestamp(timestampUs, msgType, dataCopy); 299c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra } 30065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 30165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 30265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatrabool CameraSourceTimeLapse::skipCurrentFrame(int64_t timestampUs) { 303c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra if (mSkipCurrentFrame) { 30465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mSkipCurrentFrame = false; 30565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra return true; 30665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } else { 30765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra return false; 30865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } 30965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 31065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 31165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatrabool CameraSourceTimeLapse::skipFrameAndModifyTimeStamp(int64_t *timestampUs) { 312c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra if (!mUseStillCameraForTimeLapse) { 313c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra if (mLastTimeLapseFrameRealTimestampUs == 0) { 31465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // First time lapse frame. Initialize mLastTimeLapseFrameRealTimestampUs 31565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // to current time (timestampUs) and save frame data. 31665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra LOGV("dataCallbackTimestamp timelapse: initial frame"); 31765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 31865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mLastTimeLapseFrameRealTimestampUs = *timestampUs; 31965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } else if (*timestampUs < 32065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenTimeLapseFrameCaptureUs)) { 32165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // Skip all frames from last encoded frame until 32265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // sufficient time (mTimeBetweenTimeLapseFrameCaptureUs) has passed. 32365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // Tell the camera to release its recording frame and return. 32465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra LOGV("dataCallbackTimestamp timelapse: skipping intermediate frame"); 32565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra return true; 32665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } else { 32765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // Desired frame has arrived after mTimeBetweenTimeLapseFrameCaptureUs time: 32865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // - Reset mLastTimeLapseFrameRealTimestampUs to current time. 32965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // - Artificially modify timestampUs to be one frame time (1/framerate) ahead 33065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // of the last encoded frame's time stamp. 33165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra LOGV("dataCallbackTimestamp timelapse: got timelapse frame"); 33265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 33365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mLastTimeLapseFrameRealTimestampUs = *timestampUs; 33465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs; 33565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } 33665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } 33765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra return false; 33865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 33965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 34065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSourceTimeLapse::dataCallbackTimestamp(int64_t timestampUs, int32_t msgType, 34165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra const sp<IMemory> &data) { 342c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra if (!mUseStillCameraForTimeLapse) { 34365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mSkipCurrentFrame = skipFrameAndModifyTimeStamp(×tampUs); 34465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } 34565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra CameraSource::dataCallbackTimestamp(timestampUs, msgType, data); 34665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 34765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 34865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} // namespace android 349