Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d941323 authored by Chong Zhang's avatar Chong Zhang Committed by Android Git Automerger
Browse files

am dd761ece: Merge "MediaRecorder: enable audio for slow motion recording" into mnc-dev

* commit 'dd761ece':
  MediaRecorder: enable audio for slow motion recording
parents 283f0fd8 dd761ece
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -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;
+55 −35
Original line number Diff line number Diff line
@@ -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();
+4 −5
Original line number Diff line number Diff line
@@ -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);
+16 −3
Original line number Diff line number Diff line
@@ -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;
}