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

Commit eff30e3d authored by James Dong's avatar James Dong
Browse files

Change the default time scale for audio/video track during recording

and reduce rounding errors in calculating the sample duration

- Default time scale for tracks other than audio is set to 90000.
- Audio track by default uses the audio sampling rate as the time scale.
- Default movie time scale remains to be 1000.
- The default time scale values will be overwritten by a user-supplied value if exits.

Change-Id: I81b40ed0626ea45e9fd24a89e21a2c5a4a2c3415
parent 997dc32b
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -675,7 +675,9 @@ sp<MediaSource> StagefrightRecorder::createAudioSource() {
    encMeta->setInt32(kKeyChannelCount, mAudioChannels);
    encMeta->setInt32(kKeySampleRate, mSampleRate);
    encMeta->setInt32(kKeyBitRate, mAudioBitRate);
    if (mAudioTimeScale > 0) {
        encMeta->setInt32(kKeyTimeScale, mAudioTimeScale);
    }

    OMXClient client;
    CHECK_EQ(client.connect(), OK);
@@ -961,7 +963,9 @@ status_t StagefrightRecorder::setupVideoEncoder(sp<MediaSource> *source) {
    enc_meta->setInt32(kKeyStride, stride);
    enc_meta->setInt32(kKeySliceHeight, sliceHeight);
    enc_meta->setInt32(kKeyColorFormat, colorFormat);
    if (mVideoTimeScale > 0) {
        enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale);
    }
    if (mVideoEncoderProfile != -1) {
        enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile);
    }
@@ -1041,7 +1045,9 @@ status_t StagefrightRecorder::startMPEG4Recording() {
    meta->setInt32(kKeyFileType, mOutputFormat);
    meta->setInt32(kKeyBitRate, totalBitRate);
    meta->setInt32(kKey64BitFileOffset, mUse64BitFileOffset);
    if (mMovieTimeScale > 0) {
        meta->setInt32(kKeyTimeScale, mMovieTimeScale);
    }
    if (mTrackEveryTimeDurationUs > 0) {
        meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
    }
@@ -1117,9 +1123,9 @@ status_t StagefrightRecorder::reset() {
    mIFramesIntervalSec = 1;
    mAudioSourceNode = 0;
    mUse64BitFileOffset = false;
    mMovieTimeScale  = 1000;
    mAudioTimeScale  = 1000;
    mVideoTimeScale  = 1000;
    mMovieTimeScale  = -1;
    mAudioTimeScale  = -1;
    mVideoTimeScale  = -1;
    mCameraId        = 0;
    mVideoEncoderProfile = -1;
    mVideoEncoderLevel   = -1;
+51 −8
Original line number Diff line number Diff line
@@ -168,6 +168,12 @@ private:

    void getCodecSpecificDataFromInputFormatIfPossible();

    // Determine the track time scale
    // If it is an audio track, try to use the sampling rate as
    // the time scale; however, if user chooses the overwrite
    // value, the user-supplied time scale will be used.
    void setTimeScale();

    Track(const Track &);
    Track &operator=(const Track &);
};
@@ -434,7 +440,7 @@ void MPEG4Writer::stop() {
    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
    mMoovBoxBufferOffset = 0;
    CHECK(mMoovBoxBuffer != NULL);
    int32_t duration = (maxDurationUs * mTimeScale) / 1E6;
    int32_t duration = (maxDurationUs * mTimeScale + 5E5) / 1E6;

    beginBox("moov");

@@ -749,10 +755,6 @@ MPEG4Writer::Track::Track(
      mReachedEOS(false) {
    getCodecSpecificDataFromInputFormatIfPossible();

    if (!mMeta->findInt32(kKeyTimeScale, &mTimeScale)) {
        mTimeScale = 1000;
    }

    const char *mime;
    mMeta->findCString(kKeyMIMEType, &mime);
    mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
@@ -760,6 +762,28 @@ MPEG4Writer::Track::Track(
    mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
               !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);

    setTimeScale();
}

void MPEG4Writer::Track::setTimeScale() {
    LOGV("setTimeScale");
    // Default time scale
    mTimeScale = 90000;

    if (mIsAudio) {
        // Use the sampling rate as the default time scale for audio track.
        int32_t sampleRate;
        bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
        CHECK(success);
        mTimeScale = sampleRate;
    }

    // If someone would like to overwrite the timescale, use user-supplied value.
    int32_t timeScale;
    if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
        mTimeScale = timeScale;
    }

    CHECK(mTimeScale > 0);
}

@@ -1336,6 +1360,8 @@ void MPEG4Writer::Track::threadEntry() {
    int32_t nZeroLengthFrames = 0;
    int64_t lastTimestampUs = 0;  // Previous sample time stamp in ms
    int64_t lastDurationUs = 0;   // Between the previous two samples in ms
    int64_t currDurationTicks = 0;  // Timescale based ticks
    int64_t lastDurationTicks = 0;  // Timescale based ticks
    int32_t sampleCount = 1;      // Sample count in the current stts table entry
    uint32_t previousSampleSize = 0;  // Size of the previous sample
    int64_t previousPausedDurationUs = 0;
@@ -1483,7 +1509,16 @@ void MPEG4Writer::Track::threadEntry() {
        mSampleSizes.push_back(sampleSize);
        ++mNumSamples;
        if (mNumSamples > 2) {
            if (lastDurationUs != timestampUs - lastTimestampUs) {
            // We need to use the time scale based ticks, rather than the
            // timestamp itself to determine whether we have to use a new
            // stts entry, since we may have rounding errors.
            // The calculation is intended to reduce the accumulated
            // rounding errors.
            currDurationTicks =
                     ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
                     (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);

            if (currDurationTicks != lastDurationTicks) {
                SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
                mSttsTableEntries.push_back(sttsEntry);
                sampleCount = 1;
@@ -1498,6 +1533,7 @@ void MPEG4Writer::Track::threadEntry() {
            previousSampleSize = sampleSize;
        }
        lastDurationUs = timestampUs - lastTimestampUs;
        lastDurationTicks = currDurationTicks;
        lastTimestampUs = timestampUs;
        if (mIsRealTimeRecording && mIsAudio) {
            wallClockTimeUs = systemTime() / 1000;
@@ -1774,7 +1810,6 @@ void MPEG4Writer::Track::writeTrackHeader(
    LOGV("%s track time scale: %d",
        mIsAudio? "Audio": "Video", mTimeScale);


    time_t now = time(NULL);
    int32_t mvhdTimeScale = mOwner->getTimeScale();
    int64_t trakDurationUs = getDurationUs();
@@ -2089,10 +2124,18 @@ void MPEG4Writer::Track::writeTrackHeader(
          mOwner->beginBox("stts");
            mOwner->writeInt32(0);  // version=0, flags=0
            mOwner->writeInt32(mSttsTableEntries.size());
            int64_t prevTimestampUs = 0;
            for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
                 it != mSttsTableEntries.end(); ++it) {
                mOwner->writeInt32(it->sampleCount);
                int32_t dur = (it->sampleDurationUs * mTimeScale + 5E5) / 1E6;

                // Make sure that we are calculating the sample duration the exactly
                // same way as we made decision on how to create stts entries.
                int64_t currTimestampUs = prevTimestampUs + it->sampleDurationUs;
                int32_t dur = ((currTimestampUs * mTimeScale + 500000LL) / 1000000LL -
                               (prevTimestampUs * mTimeScale + 500000LL) / 1000000LL);
                prevTimestampUs += (it->sampleCount * it->sampleDurationUs);

                mOwner->writeInt32(dur);
            }
          mOwner->endBox();  // stts