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#ifndef CAMERA_SOURCE_TIME_LAPSE_H_ 1865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 1965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#define CAMERA_SOURCE_TIME_LAPSE_H_ 2065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 2165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <pthread.h> 2265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 2365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <utils/RefBase.h> 2465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <utils/threads.h> 25ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala#include <utils/String16.h> 2665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 2765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatranamespace android { 2865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 29d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvalanamespace hardware { 3065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatraclass ICamera; 31d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala} 32d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 3365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatraclass IMemory; 3465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatraclass Camera; 3565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 3665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatraclass CameraSourceTimeLapse : public CameraSource { 3765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatrapublic: 3854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong static CameraSourceTimeLapse *CreateFromCamera( 39d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala const sp<hardware::ICamera> &camera, 404ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li const sp<ICameraRecordingProxy> &proxy, 4154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t cameraId, 42ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala const String16& clientName, 43ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala uid_t clientUid, 4498a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen pid_t clientPid, 4554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong Size videoSize, 4654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t videoFrameRate, 4799617adda9bc46c43f511f0940bc735c73de61deMathias Agopian const sp<IGraphicBufferProducer>& surface, 489c7f845780d62ea09469a8dac7117cc01adfea5cLajos Molnar int64_t timeBetweenTimeLapseFrameCaptureUs, 499c7f845780d62ea09469a8dac7117cc01adfea5cLajos Molnar bool storeMetaDataInVideoBuffers = true); 5065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 5165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra virtual ~CameraSourceTimeLapse(); 5265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 5378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // If the frame capture interval is large, read will block for a long time. 5478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // Due to the way the mediaRecorder framework works, a stop() call from 5578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // mediaRecorder waits until the read returns, causing a long wait for 5678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // stop() to return. To avoid this, we can make read() return a copy of the 5778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // last read frame with the same time stamp frequently. This keeps the 5878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // read() call from blocking too long. Calling this function quickly 5978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // captures another frame, keeps its copy, and enables this mode of read() 6078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // returning quickly. 6178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra void startQuickReadReturns(); 6278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra 6365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatraprivate: 64c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra // size of the encoded video. 65c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra int32_t mVideoWidth; 66c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra int32_t mVideoHeight; 67c4e47d1e81c4e4403663cb911e98dbf3ada9942cNipun Kwatra 6865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // Time between two frames in final video (1/frameRate) 6965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra int64_t mTimeBetweenTimeLapseVideoFramesUs; 7065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 7165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // Real timestamp of the last encoded time lapse frame 7265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra int64_t mLastTimeLapseFrameRealTimestampUs; 7365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 7465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // Variable set in dataCallbackTimestamp() to help skipCurrentFrame() 7565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // to know if current frame needs to be skipped. 7665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra bool mSkipCurrentFrame; 7765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 7878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // Lock for accessing mCameraIdle 7978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra Mutex mCameraIdleLock; 8078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra 8178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // Condition variable to wait on if camera is is not yet idle. Once the 8278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // camera gets idle, this variable will be signalled. 8378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra Condition mCameraIdleCondition; 8478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra 850aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra // True if camera is in preview mode and ready for takePicture(). 8678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // False after a call to takePicture() but before the final compressed 8778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // data callback has been called and preview has been restarted. 8878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra volatile bool mCameraIdle; 8978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra 9078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // True if stop() is waiting for camera to get idle, i.e. for the last 9178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // takePicture() to complete. This is needed so that dataCallbackTimestamp() 9278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // can return immediately. 9378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra volatile bool mStopWaitingForIdleCamera; 9478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra 9578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // Lock for accessing quick stop variables. 9678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra Mutex mQuickStopLock; 9778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra 9878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // mQuickStop is set to true if we use quick read() returns, otherwise it is set 9978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // to false. Once in this mode read() return a copy of the last read frame 10078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // with the same time stamp. See startQuickReadReturns(). 10178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra volatile bool mQuickStop; 10278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra 10378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // Forces the next frame passed to dataCallbackTimestamp() to be read 10478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // as a time lapse frame. Used by startQuickReadReturns() so that the next 10578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // frame wakes up any blocking read. 10678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra volatile bool mForceRead; 10778eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra 10878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // Stores a copy of the MediaBuffer read in the last read() call after 10978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // mQuickStop was true. 11078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra MediaBuffer* mLastReadBufferCopy; 11178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra 11278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // Status code for last read. 11378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra status_t mLastReadStatus; 1140aacf105eea098a0b47761a4a9a5c4d820611f2dNipun Kwatra 11554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong CameraSourceTimeLapse( 116d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala const sp<hardware::ICamera> &camera, 1174ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li const sp<ICameraRecordingProxy> &proxy, 11854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t cameraId, 119ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala const String16& clientName, 120ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala uid_t clientUid, 12198a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen pid_t clientPid, 12254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong Size videoSize, 12354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t videoFrameRate, 12499617adda9bc46c43f511f0940bc735c73de61deMathias Agopian const sp<IGraphicBufferProducer>& surface, 1259c7f845780d62ea09469a8dac7117cc01adfea5cLajos Molnar int64_t timeBetweenTimeLapseFrameCaptureUs, 1269c7f845780d62ea09469a8dac7117cc01adfea5cLajos Molnar bool storeMetaDataInVideoBuffers = true); 12765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 12878eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // Wrapper over CameraSource::signalBufferReturned() to implement quick stop. 12978eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // It only handles the case when mLastReadBufferCopy is signalled. Otherwise 13078eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // it calls the base class' function. 13178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra virtual void signalBufferReturned(MediaBuffer* buffer); 13278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra 13378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // Wrapper over CameraSource::read() to implement quick stop. 13478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL); 13578eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra 13665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // mSkipCurrentFrame is set to true in dataCallbackTimestamp() if the current 13765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // frame needs to be skipped and this function just returns the value of mSkipCurrentFrame. 13865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra virtual bool skipCurrentFrame(int64_t timestampUs); 13965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 14065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // In the video camera case calls skipFrameAndModifyTimeStamp() to modify 14165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // timestamp and set mSkipCurrentFrame. 14265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // Then it calls the base CameraSource::dataCallbackTimestamp() 1438fc3c670fff26cb21d1e16dbfcbc4410d7758574Chien-Yu Chen // This will be called in VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV and 1448fc3c670fff26cb21d1e16dbfcbc4410d7758574Chien-Yu Chen // VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA mode. 14565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra virtual void dataCallbackTimestamp(int64_t timestampUs, int32_t msgType, 14665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra const sp<IMemory> &data); 14765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 1482d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen // In the video camera case calls skipFrameAndModifyTimeStamp() to modify 1492d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen // timestamp and set mSkipCurrentFrame. 150b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh // Then it calls the base CameraSource::recordingFrameHandleCallbackTimestamp() or 151b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh // CameraSource::recordingFrameHandleCallbackTimestampBatch() 1522d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen // This will be called in VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA mode when 1532d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen // the metadata is VideoNativeHandleMetadata. 1542d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen virtual void recordingFrameHandleCallbackTimestamp(int64_t timestampUs, 1552d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen native_handle_t* handle); 1562d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen 157b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh // In the video camera case calls skipFrameAndModifyTimeStamp() to modify 158b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh // timestamp and set mSkipCurrentFrame. 159b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh // Then it calls the base CameraSource::recordingFrameHandleCallbackTimestamp() or 160b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh // CameraSource::recordingFrameHandleCallbackTimestampBatch() 161b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh // This will be called in VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA mode when 162b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh // the metadata is VideoNativeHandleMetadata. 163b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh virtual void recordingFrameHandleCallbackTimestampBatch( 164b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh const std::vector<int64_t>& timestampsUs, 165b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh const std::vector<native_handle_t*>& handles); 166b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh 1678fc3c670fff26cb21d1e16dbfcbc4410d7758574Chien-Yu Chen // Process a buffer item received in CameraSource::BufferQueueListener. 1688fc3c670fff26cb21d1e16dbfcbc4410d7758574Chien-Yu Chen // This will be called in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode. 1698fc3c670fff26cb21d1e16dbfcbc4410d7758574Chien-Yu Chen virtual void processBufferQueueFrame(BufferItem& buffer); 1708fc3c670fff26cb21d1e16dbfcbc4410d7758574Chien-Yu Chen 17178eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // Convenience function to fill mLastReadBufferCopy from the just read 17278eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra // buffer. 17378eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra void fillLastReadBufferCopy(MediaBuffer& sourceBuffer); 17478eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra 17528934a90e168291f6c77c56e8a05f272e5151bbdJames Dong // If the passed in size (width x height) is a supported video/preview size, 17628934a90e168291f6c77c56e8a05f272e5151bbdJames Dong // the function sets the camera's video/preview size to it and returns true. 177155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra // Otherwise returns false. 17828934a90e168291f6c77c56e8a05f272e5151bbdJames Dong bool trySettingVideoSize(int32_t width, int32_t height); 179155e833a7a5fc3e193691324cf9326da1bc3289aNipun Kwatra 18065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // When video camera is used for time lapse capture, returns true 18165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // until enough time has passed for the next time lapse frame. When 18265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // the frame needs to be encoded, it returns false and also modifies 18365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // the time stamp to be one frame time ahead of the last encoded 18465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // frame's time stamp. 18565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra bool skipFrameAndModifyTimeStamp(int64_t *timestampUs); 18665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 18765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // Wrapper to enter threadTimeLapseEntry() 18865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra static void *ThreadTimeLapseWrapper(void *me); 18965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 19065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // Creates a copy of source_data into a new memory of final type MemoryBase. 19165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra sp<IMemory> createIMemoryCopy(const sp<IMemory> &source_data); 19265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 19365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra CameraSourceTimeLapse(const CameraSourceTimeLapse &); 19465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra CameraSourceTimeLapse &operator=(const CameraSourceTimeLapse &); 19565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}; 19665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 19765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} // namespace android 19865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 19965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#endif // CAMERA_SOURCE_TIME_LAPSE_H_ 200