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
This commit is contained in:
@@ -33,11 +33,13 @@ class CameraSourceTimeLapse : public CameraSource {
|
||||
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 @@ private:
|
||||
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()
|
||||
|
||||
@@ -278,6 +278,23 @@ public class MediaRecorder
|
||||
setAudioEncoder(profile.audioCodec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables/Disables time lapse capture and sets its parameters. This method should
|
||||
* be called after setProfile().
|
||||
*
|
||||
* @param enableTimeLapse Pass true to enable time lapse capture, false to disable it.
|
||||
* @param timeBetweenTimeLapseFrameCaptureMs time between two captures of time lapse frames.
|
||||
* @param encoderLevel the video encoder level.
|
||||
*/
|
||||
public void setTimeLapseParameters(boolean enableTimeLapse,
|
||||
int timeBetweenTimeLapseFrameCaptureMs, int encoderLevel) {
|
||||
setParameter(String.format("time-lapse-enable=%d",
|
||||
(enableTimeLapse) ? 1 : 0));
|
||||
setParameter(String.format("time-between-time-lapse-frame-capture=%d",
|
||||
timeBetweenTimeLapseFrameCaptureMs));
|
||||
setVideoEncoderLevel(encoderLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the format of the output file produced during recording. Call this
|
||||
* after setAudioSource()/setVideoSource() but before prepare().
|
||||
@@ -444,6 +461,15 @@ public class MediaRecorder
|
||||
setParameter(String.format("video-param-encoding-bitrate=%d", bitRate));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the level of the encoder. Call this before prepare().
|
||||
*
|
||||
* @param encoderLevel the video encoder level.
|
||||
*/
|
||||
public void setVideoEncoderLevel(int encoderLevel) {
|
||||
setParameter(String.format("video-param-encoder-level=%d", encoderLevel));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass in the file descriptor of the file to be written. Call this after
|
||||
* setOutputFormat() but before prepare().
|
||||
|
||||
@@ -473,6 +473,32 @@ status_t StagefrightRecorder::setParamAudioTimeScale(int32_t timeScale) {
|
||||
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 @@ status_t StagefrightRecorder::setParameter(
|
||||
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 @@ void StagefrightRecorder::clipVideoFrameWidth() {
|
||||
}
|
||||
|
||||
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 @@ status_t StagefrightRecorder::setupCameraSource() {
|
||||
|
||||
// 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 @@ status_t StagefrightRecorder::setupCameraSource() {
|
||||
// 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 @@ status_t StagefrightRecorder::setupVideoEncoder(const sp<MediaWriter>& writer) {
|
||||
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 @@ status_t StagefrightRecorder::setupVideoEncoder(const sp<MediaWriter>& writer) {
|
||||
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 @@ status_t StagefrightRecorder::reset() {
|
||||
mMaxFileSizeBytes = 0;
|
||||
mTrackEveryTimeDurationUs = 0;
|
||||
mCaptureTimeLapse = false;
|
||||
mTimeBetweenTimeLapseFrameCaptureUs = -1;
|
||||
mEncoderProfiles = MediaProfiles::getInstance();
|
||||
|
||||
mOutputFd = -1;
|
||||
|
||||
@@ -93,6 +93,7 @@ private:
|
||||
int64_t mTrackEveryTimeDurationUs;
|
||||
|
||||
bool mCaptureTimeLapse;
|
||||
int64_t mTimeBetweenTimeLapseFrameCaptureUs;
|
||||
|
||||
String8 mParams;
|
||||
int mOutputFd;
|
||||
@@ -114,6 +115,8 @@ private:
|
||||
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);
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace android {
|
||||
// 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 @@ CameraSourceTimeLapse *CameraSourceTimeLapse::Create(bool useStillCameraForTimeL
|
||||
}
|
||||
|
||||
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 @@ CameraSourceTimeLapse::CameraSourceTimeLapse(const sp<Camera> &camera,
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user