diff options
author | James Dong <jdong@google.com> | 2011-02-16 12:28:26 -0800 |
---|---|---|
committer | James Dong <jdong@google.com> | 2011-02-17 14:43:16 -0800 |
commit | a472613aec322e25891abf5c77bf3f7e3c244920 (patch) | |
tree | 2b8aa12e87fff0c143d50022f9f413305dc7882f /media/libstagefright/MPEG4Writer.cpp | |
parent | f71eb135c28dd7b305b7030776ef0d44fac732c4 (diff) | |
download | frameworks_av-a472613aec322e25891abf5c77bf3f7e3c244920.zip frameworks_av-a472613aec322e25891abf5c77bf3f7e3c244920.tar.gz frameworks_av-a472613aec322e25891abf5c77bf3f7e3c244920.tar.bz2 |
A/V synchronization at the beginning of a recording session
o do not use edts/elst boxes since these optional boxes are ignored
o manipulate the first video/audio frame duration to make sure that the rest
of the audio/video is in sync (ideally, we should only manipulate
the vidoe frame duration, not the audio)
o reduce the initial audio mute/suppression period, which is used to
eliminate the "recording" sound.
bug - 3405882 and 3362703
Change-Id: Ib0acfb4f3843b365157288951dc122b006299c18
Diffstat (limited to 'media/libstagefright/MPEG4Writer.cpp')
-rw-r--r-- | media/libstagefright/MPEG4Writer.cpp | 60 |
1 files changed, 37 insertions, 23 deletions
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index b11789d..5d6ea7c 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -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 } - addOneSttsTableEntry(sampleCount, lastDurationUs); + + 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); |