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

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

Use audio clock as the reference media clock

o Only do this for realtime applications
o Adjust other track clock based on audio clock
o Assume other track uses wall clock as the media clock
o Use some heuristics to reduce the size of stts box by 2/3.

- also
o Remove one unused key from MetaData.h

Change-Id: Ib9432842627b61795b533508158c25258a527332
parent 6a73368b
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -128,6 +128,12 @@ private:
    // Write the first chunk from the given ChunkInfo.
    void writeFirstChunk(ChunkInfo* info);

    // Adjust other track media clock (presumably wall clock)
    // based on audio track media clock with the drift time.
    int64_t mDriftTimeUs;
    void addDriftTimeUs(int64_t driftTimeUs);
    int64_t getDriftTimeUs();

    void lock();
    void unlock();

+2 −2
Original line number Diff line number Diff line
@@ -86,10 +86,10 @@ enum {

    // Track authoring progress status
    // kKeyTrackTimeStatus is used to track progress in elapsed time
    // kKeyTrackFrameStatus is used to track progress in authored frames
    kKeyTrackFrameStatus  = 'tkfm',  // int32_t
    kKeyTrackTimeStatus   = 'tktm',  // int64_t

    kKeyNotRealTime       = 'ntrt',  // bool (int32_t)

};

enum {
+65 −0
Original line number Diff line number Diff line
@@ -72,6 +72,11 @@ private:
    bool mIsAudio;
    bool mIsMPEG4;
    int64_t mTrackDurationUs;

    // For realtime applications, we need to adjust the media clock
    // for video track based on the audio media clock
    bool mIsRealTimeRecording;
    int64_t mMaxTimeStampUs;
    int64_t mEstimatedTrackSizeBytes;
    int64_t mMaxWriteTimeUs;
    int32_t mTimeScale;
@@ -940,6 +945,7 @@ status_t MPEG4Writer::startWriterThread() {

    mDone = false;
    mIsFirstChunk = true;
    mDriftTimeUs = 0;
    for (List<Track *>::iterator it = mTracks.begin();
         it != mTracks.end(); ++it) {
        ChunkInfo info;
@@ -967,6 +973,14 @@ status_t MPEG4Writer::Track::start(MetaData *params) {
        startTimeUs = 0;
    }

    mIsRealTimeRecording = true;
    {
        int32_t isNotRealTime;
        if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
            mIsRealTimeRecording = (isNotRealTime == 0);
        }
    }

    initTrackingProgressStatus(params);

    sp<MetaData> meta = new MetaData;
@@ -1326,6 +1340,10 @@ void MPEG4Writer::Track::threadEntry() {
    uint32_t previousSampleSize = 0;  // Size of the previous sample
    int64_t previousPausedDurationUs = 0;
    int64_t timestampUs;

    int64_t wallClockTimeUs = 0;
    int64_t lastWallClockTimeUs = 0;

    sp<MetaData> meta_data;
    bool collectStats = collectStatisticalData();

@@ -1429,6 +1447,33 @@ void MPEG4Writer::Track::threadEntry() {
        }

        timestampUs -= previousPausedDurationUs;
        if (mIsRealTimeRecording && !mIsAudio) {
            // The minor adjustment on the timestamp is heuristic/experimental
            // We are adjusting the timestamp to reduce the fluctuation of the duration
            // of neighboring samples. This in turn helps reduce the track header size,
            // especially, the number of entries in the "stts" box.
            if (mNumSamples > 1) {
                int64_t durationUs = timestampUs + mOwner->getDriftTimeUs() - lastTimestampUs;
                int64_t diffUs = (durationUs > lastDurationUs)
                            ? durationUs - lastDurationUs
                            : lastDurationUs - durationUs;
                if (diffUs <= 5000) {  // XXX: Magic number 5ms
                    timestampUs = lastTimestampUs + lastDurationUs;
                } else {
                    timestampUs += mOwner->getDriftTimeUs();
                }
            }
        }
        CHECK(timestampUs >= 0);
        if (mNumSamples > 1) {
            if (timestampUs <= lastTimestampUs) {
                LOGW("Drop a frame, since it arrives too late!");
                copy->release();
                copy = NULL;
                continue;
            }
        }

        LOGV("time stamp: %lld and previous paused duration %lld",
                timestampUs, previousPausedDurationUs);
        if (timestampUs > mTrackDurationUs) {
@@ -1454,6 +1499,14 @@ void MPEG4Writer::Track::threadEntry() {
        }
        lastDurationUs = timestampUs - lastTimestampUs;
        lastTimestampUs = timestampUs;
        if (mIsRealTimeRecording && mIsAudio) {
            wallClockTimeUs = systemTime() / 1000;
            int64_t wallClockDurationUs = wallClockTimeUs - lastWallClockTimeUs;
            if (mNumSamples > 2) {
                mOwner->addDriftTimeUs(lastDurationUs - wallClockDurationUs);
            }
            lastWallClockTimeUs = wallClockTimeUs;
        }

        if (isSync != 0) {
            mStssTableEntries.push_back(mNumSamples);
@@ -1679,6 +1732,18 @@ void MPEG4Writer::Track::logStatisticalData(bool isAudio) {
    }
}

void MPEG4Writer::addDriftTimeUs(int64_t driftTimeUs) {
    LOGV("addDriftTimeUs: %lld us", driftTimeUs);
    Mutex::Autolock autolock(mLock);
    mDriftTimeUs += driftTimeUs;
}

int64_t MPEG4Writer::getDriftTimeUs() {
    LOGV("getDriftTimeUs: %lld us", mDriftTimeUs);
    Mutex::Autolock autolock(mLock);
    return mDriftTimeUs;
}

void MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
    LOGV("bufferChunk");