Allowing setting of time lapse parameters through MediaRecorder.java

added setTimeLapseParameters() to MediaRecorder.java and SetParameter support
in StagefrightRecorder to allow enabling time lapse and setting the corresponding
parameters.

Change-Id: I509040aa71f8d3fc37337b0894a81d9c0fd7a40a
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
index f153f09..fa11b3e 100644
--- a/include/media/stagefright/CameraSourceTimeLapse.h
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -33,11 +33,13 @@
 public:
     static CameraSourceTimeLapse *Create(bool useStillCameraForTimeLapse,
         int64_t timeBetweenTimeLapseFrameCaptureUs,
+        int32_t width, int32_t height,
         int32_t videoFrameRate);
 
     static CameraSourceTimeLapse *CreateFromCamera(const sp<Camera> &camera,
         bool useStillCameraForTimeLapse,
         int64_t timeBetweenTimeLapseFrameCaptureUs,
+        int32_t width, int32_t height,
         int32_t videoFrameRate);
 
     virtual ~CameraSourceTimeLapse();
@@ -70,6 +72,7 @@
     CameraSourceTimeLapse(const sp<Camera> &camera,
         bool useStillCameraForTimeLapse,
         int64_t timeBetweenTimeLapseFrameCaptureUs,
+        int32_t width, int32_t height,
         int32_t videoFrameRate);
 
     // For still camera case starts a thread which calls camera's takePicture()
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 3dbcfd5..f747f90 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -473,6 +473,32 @@
     return OK;
 }
 
+status_t StagefrightRecorder::setParamTimeLapseEnable(int32_t timeLapseEnable) {
+    LOGV("setParamTimeLapseEnable: %d", timeLapseEnable);
+
+    if(timeLapseEnable == 0) {
+        mCaptureTimeLapse = false;
+    } else if (timeLapseEnable == 1) {
+        mCaptureTimeLapse = true;
+    } else {
+        return BAD_VALUE;
+    }
+    return OK;
+}
+
+status_t StagefrightRecorder::setParamTimeBetweenTimeLapseFrameCapture(int64_t timeUs) {
+    LOGV("setParamTimeBetweenTimeLapseFrameCapture: %lld us", timeUs);
+
+    // Not allowing time more than a day
+    if (timeUs <= 0 || timeUs > 86400*1E6) {
+        LOGE("Time between time lapse frame capture (%lld) is out of range [0, 1 Day]", timeUs);
+        return BAD_VALUE;
+    }
+
+    mTimeBetweenTimeLapseFrameCaptureUs = timeUs;
+    return OK;
+}
+
 status_t StagefrightRecorder::setParameter(
         const String8 &key, const String8 &value) {
     LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
@@ -556,6 +582,17 @@
         if (safe_strtoi32(value.string(), &timeScale)) {
             return setParamVideoTimeScale(timeScale);
         }
+    } else if (key == "time-lapse-enable") {
+        int32_t timeLapseEnable;
+        if (safe_strtoi32(value.string(), &timeLapseEnable)) {
+            return setParamTimeLapseEnable(timeLapseEnable);
+        }
+    } else if (key == "time-between-time-lapse-frame-capture") {
+        int64_t timeBetweenTimeLapseFrameCaptureMs;
+        if (safe_strtoi64(value.string(), &timeBetweenTimeLapseFrameCaptureMs)) {
+            return setParamTimeBetweenTimeLapseFrameCapture(
+                    1000LL * timeBetweenTimeLapseFrameCaptureMs);
+        }
     } else {
         LOGE("setParameter: failed to find key %s", key.string());
     }
@@ -813,10 +850,14 @@
 }
 
 status_t StagefrightRecorder::setupCameraSource() {
-    clipVideoBitRate();
-    clipVideoFrameRate();
-    clipVideoFrameWidth();
-    clipVideoFrameHeight();
+    if(!mCaptureTimeLapse) {
+        // Dont clip for time lapse capture as encoder will have enough
+        // time to encode because of slow capture rate of time lapse.
+        clipVideoBitRate();
+        clipVideoFrameRate();
+        clipVideoFrameWidth();
+        clipVideoFrameHeight();
+    }
 
     int64_t token = IPCThreadState::self()->clearCallingIdentity();
     if (mCamera == 0) {
@@ -831,7 +872,13 @@
 
     // Set the actual video recording frame size
     CameraParameters params(mCamera->getParameters());
-    params.setPreviewSize(mVideoWidth, mVideoHeight);
+
+    // dont change the preview size for time lapse as mVideoWidth, mVideoHeight
+    // may correspond to HD resolution not supported by video camera.
+    if (!mCaptureTimeLapse) {
+        params.setPreviewSize(mVideoWidth, mVideoHeight);
+    }
+
     params.setPreviewFrameRate(mFrameRate);
     String8 s = params.flatten();
     CHECK_EQ(OK, mCamera->setParameters(s));
@@ -840,8 +887,9 @@
     // Check on video frame size
     int frameWidth = 0, frameHeight = 0;
     newCameraParams.getPreviewSize(&frameWidth, &frameHeight);
-    if (frameWidth  < 0 || frameWidth  != mVideoWidth ||
-        frameHeight < 0 || frameHeight != mVideoHeight) {
+    if (!mCaptureTimeLapse &&
+        (frameWidth  < 0 || frameWidth  != mVideoWidth ||
+        frameHeight < 0 || frameHeight != mVideoHeight)) {
         LOGE("Failed to set the video frame size to %dx%d",
                 mVideoWidth, mVideoHeight);
         IPCThreadState::self()->restoreCallingIdentity(token);
@@ -882,7 +930,8 @@
     if (err != OK) return err;
 
     sp<CameraSource> cameraSource = (mCaptureTimeLapse) ?
-        CameraSourceTimeLapse::CreateFromCamera(mCamera, true, 3E6, mFrameRate):
+        CameraSourceTimeLapse::CreateFromCamera(mCamera, true,
+                mTimeBetweenTimeLapseFrameCaptureUs, mVideoWidth, mVideoHeight, mFrameRate):
         CameraSource::CreateFromCamera(mCamera);
     CHECK(cameraSource != NULL);
 
@@ -934,6 +983,7 @@
     OMXClient client;
     CHECK_EQ(client.connect(), OK);
 
+    // Use software codec for time lapse
     uint32_t encoder_flags = (mCaptureTimeLapse) ? OMXCodec::kPreferSoftwareCodecs : 0;
     sp<MediaSource> encoder = OMXCodec::Create(
             client.interface(), enc_meta,
@@ -1081,6 +1131,7 @@
     mMaxFileSizeBytes = 0;
     mTrackEveryTimeDurationUs = 0;
     mCaptureTimeLapse = false;
+    mTimeBetweenTimeLapseFrameCaptureUs = -1;
     mEncoderProfiles = MediaProfiles::getInstance();
 
     mOutputFd = -1;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 232fc0e..fc287a2 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -93,6 +93,7 @@
     int64_t mTrackEveryTimeDurationUs;
 
     bool mCaptureTimeLapse;
+    int64_t mTimeBetweenTimeLapseFrameCaptureUs;
 
     String8 mParams;
     int mOutputFd;
@@ -114,6 +115,8 @@
     status_t setParamAudioNumberOfChannels(int32_t channles);
     status_t setParamAudioSamplingRate(int32_t sampleRate);
     status_t setParamAudioTimeScale(int32_t timeScale);
+    status_t setParamTimeLapseEnable(int32_t timeLapseEnable);
+    status_t setParamTimeBetweenTimeLapseFrameCapture(int64_t timeUs);
     status_t setParamVideoEncodingBitRate(int32_t bitRate);
     status_t setParamVideoIFramesInterval(int32_t seconds);
     status_t setParamVideoEncoderProfile(int32_t profile);
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index 30ed143..c6186f6 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -33,6 +33,7 @@
 // static
 CameraSourceTimeLapse *CameraSourceTimeLapse::Create(bool useStillCameraForTimeLapse,
         int64_t timeBetweenTimeLapseFrameCaptureUs,
+        int32_t width, int32_t height,
         int32_t videoFrameRate) {
     sp<Camera> camera = Camera::connect(0);
 
@@ -41,25 +42,27 @@
     }
 
     return new CameraSourceTimeLapse(camera, useStillCameraForTimeLapse,
-            timeBetweenTimeLapseFrameCaptureUs, videoFrameRate);
+            timeBetweenTimeLapseFrameCaptureUs, width, height, videoFrameRate);
 }
 
 // static
 CameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera(const sp<Camera> &camera,
         bool useStillCameraForTimeLapse,
         int64_t timeBetweenTimeLapseFrameCaptureUs,
+        int32_t width, int32_t height,
         int32_t videoFrameRate) {
     if (camera.get() == NULL) {
         return NULL;
     }
 
     return new CameraSourceTimeLapse(camera, useStillCameraForTimeLapse,
-            timeBetweenTimeLapseFrameCaptureUs, videoFrameRate);
+            timeBetweenTimeLapseFrameCaptureUs, width, height, videoFrameRate);
 }
 
 CameraSourceTimeLapse::CameraSourceTimeLapse(const sp<Camera> &camera,
         bool useStillCameraForTimeLapse,
         int64_t timeBetweenTimeLapseFrameCaptureUs,
+        int32_t width, int32_t height,
         int32_t videoFrameRate)
     : CameraSource(camera),
       mUseStillCameraForTimeLapse(useStillCameraForTimeLapse),
@@ -70,11 +73,6 @@
 
     LOGV("starting time lapse mode");
     if(mUseStillCameraForTimeLapse) {
-        // Currently hardcoded the picture size. Will need to choose
-        // automatically or pass in from the app.
-        int32_t width, height;
-        width = 1024;
-        height = 768;
         mMeta->setInt32(kKeyWidth, width);
         mMeta->setInt32(kKeyHeight, height);
     }