diff options
| author | Chong Zhang <chz@google.com> | 2015-07-17 21:25:31 +0000 | 
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-07-17 21:25:31 +0000 | 
| commit | dd761ecee86cc24ac8774bf1f004ea29b1e0d3f7 (patch) | |
| tree | 3b2293036ff4a6dfec5624a2907b4929659b26e0 | |
| parent | 51d0b1d84dc1c095e68126257213f24f64ab3aa0 (diff) | |
| parent | 46d26dd29195450db15704e84d65740628a821fb (diff) | |
| download | frameworks_av-dd761ecee86cc24ac8774bf1f004ea29b1e0d3f7.zip frameworks_av-dd761ecee86cc24ac8774bf1f004ea29b1e0d3f7.tar.gz frameworks_av-dd761ecee86cc24ac8774bf1f004ea29b1e0d3f7.tar.bz2  | |
Merge "MediaRecorder: enable audio for slow motion recording" into mnc-dev
| -rw-r--r-- | include/media/stagefright/AudioSource.h | 5 | ||||
| -rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.cpp | 90 | ||||
| -rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.h | 9 | ||||
| -rw-r--r-- | media/libstagefright/AudioSource.cpp | 19 | 
4 files changed, 79 insertions, 44 deletions
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h index 50cf371..3074910 100644 --- a/include/media/stagefright/AudioSource.h +++ b/include/media/stagefright/AudioSource.h @@ -37,7 +37,8 @@ struct AudioSource : public MediaSource, public MediaBufferObserver {              audio_source_t inputSource,              const String16 &opPackageName,              uint32_t sampleRate, -            uint32_t channels = 1); +            uint32_t channels, +            uint32_t outSampleRate = 0);      status_t initCheck() const; @@ -78,11 +79,13 @@ private:      status_t mInitCheck;      bool mStarted;      int32_t mSampleRate; +    int32_t mOutSampleRate;      bool mTrackMaxAmplitude;      int64_t mStartTimeUs;      int16_t mMaxAmplitude;      int64_t mPrevSampleTimeUs; +    int64_t mFirstSampleTimeUs;      int64_t mInitialReadTimeUs;      int64_t mNumFramesReceived;      int64_t mNumClientOwnedBuffers; 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<MediaSource> 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> 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<CameraSourceTimeLapse> 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); diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp index 34f0148..3505844 100644 --- a/media/libstagefright/AudioSource.cpp +++ b/media/libstagefright/AudioSource.cpp @@ -50,15 +50,19 @@ static void AudioRecordCallbackFunction(int event, void *user, void *info) {  }  AudioSource::AudioSource( -        audio_source_t inputSource, const String16 &opPackageName, uint32_t sampleRate, -        uint32_t channelCount) +        audio_source_t inputSource, const String16 &opPackageName, +        uint32_t sampleRate, uint32_t channelCount, uint32_t outSampleRate)      : mStarted(false),        mSampleRate(sampleRate), +      mOutSampleRate(outSampleRate > 0 ? outSampleRate : sampleRate),        mPrevSampleTimeUs(0), +      mFirstSampleTimeUs(-1ll),        mNumFramesReceived(0),        mNumClientOwnedBuffers(0) { -    ALOGV("sampleRate: %d, channelCount: %d", sampleRate, channelCount); +    ALOGV("sampleRate: %u, outSampleRate: %u, channelCount: %u", +            sampleRate, outSampleRate, channelCount);      CHECK(channelCount == 1 || channelCount == 2); +    CHECK(sampleRate > 0);      size_t minFrameCount;      status_t status = AudioRecord::getMinFrameCount(&minFrameCount, @@ -261,6 +265,15 @@ status_t AudioSource::read(              (int16_t *) buffer->data(), buffer->range_length() >> 1);      } +    if (mSampleRate != mOutSampleRate) { +        if (mFirstSampleTimeUs < 0) { +            mFirstSampleTimeUs = timeUs; +        } +        timeUs = mFirstSampleTimeUs + (timeUs - mFirstSampleTimeUs) +                * (int64_t)mSampleRate / (int64_t)mOutSampleRate; +        buffer->meta_data()->setInt64(kKeyTime, timeUs); +    } +      *out = buffer;      return OK;  }  | 
