From 46d26dd29195450db15704e84d65740628a821fb Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Thu, 16 Jul 2015 10:48:15 -0700 Subject: MediaRecorder: enable audio for slow motion recording bug:22460747 Change-Id: I23f773ecf7b86928a8eacd25a481636e645affbe --- .../libmediaplayerservice/StagefrightRecorder.cpp | 90 +++++++++++++--------- media/libmediaplayerservice/StagefrightRecorder.h | 9 +-- 2 files changed, 59 insertions(+), 40 deletions(-) (limited to 'media/libmediaplayerservice') diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 98abe9c..e521fae 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -75,8 +75,6 @@ StagefrightRecorder::StagefrightRecorder(const String16 &opPackageName) mOutputFd(-1), mAudioSource(AUDIO_SOURCE_CNT), mVideoSource(VIDEO_SOURCE_LIST_END), - mCaptureTimeLapse(false), - mCaptureFps(0.0f), mStarted(false) { ALOGV("Constructor"); @@ -567,32 +565,32 @@ status_t StagefrightRecorder::setParamAudioTimeScale(int32_t timeScale) { return OK; } -status_t StagefrightRecorder::setParamTimeLapseEnable(int32_t timeLapseEnable) { - ALOGV("setParamTimeLapseEnable: %d", timeLapseEnable); +status_t StagefrightRecorder::setParamCaptureFpsEnable(int32_t captureFpsEnable) { + ALOGV("setParamCaptureFpsEnable: %d", captureFpsEnable); - if(timeLapseEnable == 0) { - mCaptureTimeLapse = false; - } else if (timeLapseEnable == 1) { - mCaptureTimeLapse = true; + if(captureFpsEnable == 0) { + mCaptureFpsEnable = false; + } else if (captureFpsEnable == 1) { + mCaptureFpsEnable = true; } else { return BAD_VALUE; } return OK; } -status_t StagefrightRecorder::setParamTimeLapseFps(float fps) { - ALOGV("setParamTimeLapseFps: %.2f", fps); +status_t StagefrightRecorder::setParamCaptureFps(float fps) { + ALOGV("setParamCaptureFps: %.2f", fps); int64_t timeUs = (int64_t) (1000000.0 / fps + 0.5f); // Not allowing time more than a day if (timeUs <= 0 || timeUs > 86400*1E6) { - ALOGE("Time between time lapse frame capture (%lld) is out of range [0, 1 Day]", timeUs); + ALOGE("Time between frame capture (%lld) is out of range [0, 1 Day]", timeUs); return BAD_VALUE; } mCaptureFps = fps; - mTimeBetweenTimeLapseFrameCaptureUs = timeUs; + mTimeBetweenCaptureUs = timeUs; return OK; } @@ -715,14 +713,14 @@ status_t StagefrightRecorder::setParameter( return setParamVideoTimeScale(timeScale); } } else if (key == "time-lapse-enable") { - int32_t timeLapseEnable; - if (safe_strtoi32(value.string(), &timeLapseEnable)) { - return setParamTimeLapseEnable(timeLapseEnable); + int32_t captureFpsEnable; + if (safe_strtoi32(value.string(), &captureFpsEnable)) { + return setParamCaptureFpsEnable(captureFpsEnable); } } else if (key == "time-lapse-fps") { float fps; if (safe_strtof(value.string(), &fps)) { - return setParamTimeLapseFps(fps); + return setParamCaptureFps(fps); } } else { ALOGE("setParameter: failed to find key %s", key.string()); @@ -910,12 +908,32 @@ status_t StagefrightRecorder::start() { } sp StagefrightRecorder::createAudioSource() { + int32_t sourceSampleRate = mSampleRate; + + if (mCaptureFpsEnable && mCaptureFps >= mFrameRate) { + // Upscale the sample rate for slow motion recording. + // Fail audio source creation if source sample rate is too high, as it could + // cause out-of-memory due to large input buffer size. And audio recording + // probably doesn't make sense in the scenario, since the slow-down factor + // is probably huge (eg. mSampleRate=48K, mCaptureFps=240, mFrameRate=1). + const static int32_t SAMPLE_RATE_HZ_MAX = 192000; + sourceSampleRate = + (mSampleRate * mCaptureFps + mFrameRate / 2) / mFrameRate; + if (sourceSampleRate < mSampleRate || sourceSampleRate > SAMPLE_RATE_HZ_MAX) { + ALOGE("source sample rate out of range! " + "(mSampleRate %d, mCaptureFps %.2f, mFrameRate %d", + mSampleRate, mCaptureFps, mFrameRate); + return NULL; + } + } + sp audioSource = new AudioSource( mAudioSource, mOpPackageName, - mSampleRate, - mAudioChannels); + sourceSampleRate, + mAudioChannels, + mSampleRate); status_t err = audioSource->initCheck(); @@ -1207,7 +1225,7 @@ status_t StagefrightRecorder::checkVideoEncoderCapabilities() { mVideoEncoder == VIDEO_ENCODER_H264 ? MEDIA_MIMETYPE_VIDEO_AVC : ""), false /* decoder */, true /* hwCodec */, &codecs); - if (!mCaptureTimeLapse) { + if (!mCaptureFpsEnable) { // Dont clip for time lapse capture as encoder will have enough // time to encode because of slow capture rate of time lapse. clipVideoBitRate(); @@ -1420,17 +1438,17 @@ status_t StagefrightRecorder::setupCameraSource( Size videoSize; videoSize.width = mVideoWidth; videoSize.height = mVideoHeight; - if (mCaptureTimeLapse) { - if (mTimeBetweenTimeLapseFrameCaptureUs < 0) { + if (mCaptureFpsEnable) { + if (mTimeBetweenCaptureUs < 0) { ALOGE("Invalid mTimeBetweenTimeLapseFrameCaptureUs value: %lld", - mTimeBetweenTimeLapseFrameCaptureUs); + mTimeBetweenCaptureUs); return BAD_VALUE; } mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera( mCamera, mCameraProxy, mCameraId, mClientName, mClientUid, videoSize, mFrameRate, mPreviewSurface, - mTimeBetweenTimeLapseFrameCaptureUs); + mTimeBetweenCaptureUs); *cameraSource = mCameraSourceTimeLapse; } else { *cameraSource = CameraSource::CreateFromCamera( @@ -1521,14 +1539,13 @@ status_t StagefrightRecorder::setupVideoEncoder( format->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque); // set up time lapse/slow motion for surface source - if (mCaptureTimeLapse) { - if (mTimeBetweenTimeLapseFrameCaptureUs <= 0) { - ALOGE("Invalid mTimeBetweenTimeLapseFrameCaptureUs value: %lld", - mTimeBetweenTimeLapseFrameCaptureUs); + if (mCaptureFpsEnable) { + if (mTimeBetweenCaptureUs <= 0) { + ALOGE("Invalid mTimeBetweenCaptureUs value: %lld", + mTimeBetweenCaptureUs); return BAD_VALUE; } - format->setInt64("time-lapse", - mTimeBetweenTimeLapseFrameCaptureUs); + format->setInt64("time-lapse", mTimeBetweenCaptureUs); } } @@ -1547,7 +1564,7 @@ status_t StagefrightRecorder::setupVideoEncoder( } format->setInt32("priority", 0 /* realtime */); - if (mCaptureTimeLapse) { + if (mCaptureFpsEnable) { format->setFloat("operating-rate", mCaptureFps); } @@ -1647,13 +1664,15 @@ status_t StagefrightRecorder::setupMPEG4orWEBMRecording() { // This help make sure that the "recoding" sound is suppressed for // camcorder applications in the recorded files. // TODO Audio source is currently unsupported for webm output; vorbis encoder needed. - if (!mCaptureTimeLapse && (mAudioSource != AUDIO_SOURCE_CNT)) { + // disable audio for time lapse recording + bool disableAudio = mCaptureFpsEnable && mCaptureFps < mFrameRate; + if (!disableAudio && mAudioSource != AUDIO_SOURCE_CNT) { err = setupAudioEncoder(writer); if (err != OK) return err; mTotalBitRate += mAudioBitRate; } - if (mCaptureTimeLapse) { + if (mCaptureFpsEnable) { mp4writer->setCaptureRate(mCaptureFps); } @@ -1734,7 +1753,7 @@ status_t StagefrightRecorder::stop() { ALOGV("stop"); status_t err = OK; - if (mCaptureTimeLapse && mCameraSourceTimeLapse != NULL) { + if (mCaptureFpsEnable && mCameraSourceTimeLapse != NULL) { mCameraSourceTimeLapse->startQuickReadReturns(); mCameraSourceTimeLapse = NULL; } @@ -1809,8 +1828,9 @@ status_t StagefrightRecorder::reset() { mMaxFileDurationUs = 0; mMaxFileSizeBytes = 0; mTrackEveryTimeDurationUs = 0; - mCaptureTimeLapse = false; - mTimeBetweenTimeLapseFrameCaptureUs = -1; + mCaptureFpsEnable = false; + mCaptureFps = 0.0f; + mTimeBetweenCaptureUs = -1; mCameraSourceTimeLapse = NULL; mIsMetaDataStoredInVideoBuffers = false; mEncoderProfiles = MediaProfiles::getInstance(); diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index 8af9278..da00bc7 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -111,12 +111,11 @@ private: int32_t mStartTimeOffsetMs; int32_t mTotalBitRate; - bool mCaptureTimeLapse; + bool mCaptureFpsEnable; float mCaptureFps; - int64_t mTimeBetweenTimeLapseFrameCaptureUs; + int64_t mTimeBetweenCaptureUs; sp mCameraSourceTimeLapse; - String8 mParams; bool mIsMetaDataStoredInVideoBuffers; @@ -157,8 +156,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 setParamTimeLapseFps(float fps); + status_t setParamCaptureFpsEnable(int32_t timeLapseEnable); + status_t setParamCaptureFps(float fps); status_t setParamVideoEncodingBitRate(int32_t bitRate); status_t setParamVideoIFramesInterval(int32_t seconds); status_t setParamVideoEncoderProfile(int32_t profile); -- cgit v1.1