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

Commit 5b025c46 authored by James Dong's avatar James Dong Committed by Android (Google) Code Review
Browse files

Merge "A/V synchronization at the beginning of a recording session"

parents 95fd0088 cbeebb19
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -59,11 +59,11 @@ private:

        // After the initial mute, we raise the volume linearly
        // over kAutoRampDurationUs.
        kAutoRampDurationUs = 700000,
        kAutoRampDurationUs = 300000,

        // This is the initial mute duration to suppress
        // the video recording signal tone
        kAutoRampStartUs = 1000000,
        kAutoRampStartUs = 0,
    };

    Mutex mLock;
+14 −1
Original line number Diff line number Diff line
@@ -263,6 +263,13 @@ status_t AudioSource::dataCallbackTimestamp(
        return OK;
    }

    // Drop retrieved and previously lost audio data.
    if (mNumFramesReceived == 0 && timeUs < mStartTimeUs) {
        mRecord->getInputFramesLost();
        LOGV("Drop audio data at %lld/%lld us", timeUs, mStartTimeUs);
        return OK;
    }

    if (mNumFramesReceived == 0 && mPrevSampleTimeUs == 0) {
        mInitialReadTimeUs = timeUs;
        // Initial delay
@@ -277,7 +284,13 @@ status_t AudioSource::dataCallbackTimestamp(

    int64_t timestampUs = mPrevSampleTimeUs;

    size_t numLostBytes = mRecord->getInputFramesLost();
    size_t numLostBytes = 0;
    if (mNumFramesReceived > 0) {  // Ignore earlier frame lost
        // getInputFramesLost() returns the number of lost frames.
        // Convert number of frames lost to number of bytes lost.
        numLostBytes = mRecord->getInputFramesLost() * mRecord->frameSize();
    }

    CHECK_EQ(numLostBytes & 1, 0u);
    CHECK_EQ(audioBuffer.size & 1, 0u);
    size_t bufferSize = numLostBytes + audioBuffer.size;
+3 −5
Original line number Diff line number Diff line
@@ -598,8 +598,7 @@ status_t CameraSource::stop() {
    }

    if (mNumGlitches > 0) {
        LOGW("%d long delays between neighboring video frames during",
                mNumGlitches);
        LOGW("%d long delays between neighboring video frames", mNumGlitches);
    }

    CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
@@ -696,10 +695,9 @@ void CameraSource::dataCallbackTimestamp(int64_t timestampUs,
        int32_t msgType, const sp<IMemory> &data) {
    LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
    Mutex::Autolock autoLock(mLock);
    if (!mStarted) {
    if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
        LOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs);
        releaseOneRecordingFrame(data);
        ++mNumFramesReceived;
        ++mNumFramesDropped;
        return;
    }

+37 −23
Original line number Diff line number Diff line
@@ -1281,7 +1281,21 @@ status_t MPEG4Writer::Track::start(MetaData *params) {
    initTrackingProgressStatus(params);

    sp<MetaData> meta = new MetaData;
    if (mIsRealTimeRecording && mOwner->numTracks() > 1) {
        /*
         * This extra delay of accepting incoming audio/video signals
         * helps to align a/v start time at the beginning of a recording
         * session, and it also helps eliminate the "recording" sound for
         * camcorder applications.
         *
         * Ideally, this platform-specific value should be defined
         * in media_profiles.xml file
         */
        startTimeUs += 700000;
    }

    meta->setInt64(kKeyTime, startTimeUs);

    status_t err = mSource->start(meta.get());
    if (err != OK) {
        mDone = mReachedEOS = true;
@@ -1944,7 +1958,11 @@ status_t MPEG4Writer::Track::threadEntry() {
                     ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
                     (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);

            if (currDurationTicks != lastDurationTicks) {
            // Force the first sample to have its own stts entry so that
            // we can adjust its value later to maintain the A/V sync.
            if (mNumSamples == 3 || currDurationTicks != lastDurationTicks) {
                LOGV("%s lastDurationUs: %lld us, currDurationTicks: %lld us",
                        mIsAudio? "Audio": "Video", lastDurationUs, currDurationTicks);
                addOneSttsTableEntry(sampleCount, lastDurationUs);
                sampleCount = 1;
            } else {
@@ -1957,6 +1975,8 @@ status_t MPEG4Writer::Track::threadEntry() {
            }
            previousSampleSize = sampleSize;
        }
        LOGV("%s timestampUs/lastTimestampUs: %lld/%lld",
                mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs);
        lastDurationUs = timestampUs - lastTimestampUs;
        lastDurationTicks = currDurationTicks;
        lastTimestampUs = timestampUs;
@@ -2028,7 +2048,16 @@ status_t MPEG4Writer::Track::threadEntry() {
    } else {
        ++sampleCount;  // Count for the last sample
    }

    if (mNumSamples <= 2) {
        addOneSttsTableEntry(1, lastDurationUs);
        if (sampleCount - 1 > 0) {
            addOneSttsTableEntry(sampleCount - 1, lastDurationUs);
        }
    } else {
        addOneSttsTableEntry(sampleCount, lastDurationUs);
    }

    mTrackDurationUs += lastDurationUs;
    mReachedEOS = true;
    LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
@@ -2153,6 +2182,9 @@ void MPEG4Writer::Track::writeTrackHeader(
    int32_t mvhdTimeScale = mOwner->getTimeScale();
    int64_t trakDurationUs = getDurationUs();

    // Compensate for small start time difference from different media tracks
    int64_t trackStartTimeOffsetUs = 0;

    mOwner->beginBox("trak");

      mOwner->beginBox("tkhd");
@@ -2191,26 +2223,8 @@ void MPEG4Writer::Track::writeTrackHeader(

      int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
      if (mStartTimestampUs != moovStartTimeUs) {
        mOwner->beginBox("edts");
          mOwner->beginBox("elst");
            mOwner->writeInt32(0);           // version=0, flags=0: 32-bit time
            mOwner->writeInt32(2);           // never ends with an empty list

            // First elst entry: specify the starting time offset
            int64_t offsetUs = mStartTimestampUs - moovStartTimeUs;
            LOGV("OffsetUs: %lld", offsetUs);
            int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6;
            mOwner->writeInt32(seg);         // in mvhd timecale
            mOwner->writeInt32(-1);          // starting time offset
            mOwner->writeInt32(1 << 16);     // rate = 1.0

            // Second elst entry: specify the track duration
            seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
            mOwner->writeInt32(seg);         // in mvhd timescale
            mOwner->writeInt32(0);
            mOwner->writeInt32(1 << 16);
          mOwner->endBox();
        mOwner->endBox();
          CHECK(mStartTimestampUs > moovStartTimeUs);
          trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
      }

      mOwner->beginBox("mdia");
@@ -2466,7 +2480,7 @@ void MPEG4Writer::Track::writeTrackHeader(
          mOwner->beginBox("stts");
            mOwner->writeInt32(0);  // version=0, flags=0
            mOwner->writeInt32(mNumSttsTableEntries);
            int64_t prevTimestampUs = 0;
            int64_t prevTimestampUs = trackStartTimeOffsetUs;
            for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
                 it != mSttsTableEntries.end(); ++it) {
                mOwner->writeInt32(it->sampleCount);