Revert "Revert "media: Globaly adjust timestamp to make sure all tracks' time are align""
Test: Video Recording.
This reverts commit 59f57541aee1221dd552a202c8a35d799d34979c.
Change-Id: I38e6252743235900d0cff3408d8f7f4690a2ae77
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 7e0c164..27c121f 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -112,6 +112,7 @@
int64_t getDurationUs() const;
int64_t getEstimatedTrackSizeBytes() const;
void writeTrackHeader(bool use32BitOffset = true);
+ int64_t getMinCttsOffsetTimeUs();
void bufferChunk(int64_t timestampUs);
bool isAvc() const { return mIsAvc; }
bool isHevc() const { return mIsHevc; }
@@ -307,7 +308,8 @@
ListTableEntries<uint32_t, 2> *mCttsTableEntries;
int64_t mMinCttsOffsetTimeUs;
- int64_t mMaxCttsOffsetTimeUs;
+ int64_t mMinCttsOffsetTicks;
+ int64_t mMaxCttsOffsetTicks;
// Save the last 10 frames' timestamp for debug.
std::list<std::pair<int64_t, int64_t>> mTimestampDebugHelper;
@@ -343,7 +345,7 @@
void dumpTimeStamps();
- int64_t getStartTimeOffsetScaledTimeUs() const;
+ int64_t getStartTimeOffsetTimeUs() const;
int32_t getStartTimeOffsetScaledTime() const;
static void *ThreadWrapper(void *me);
@@ -1134,9 +1136,22 @@
writeUdtaBox();
}
writeMetaBox();
- int32_t id = 1;
+ // Loop through all the tracks to get the global time offset if there is
+ // any ctts table appears in a video track.
+ int64_t minCttsOffsetTimeUs = kMaxCttsOffsetTimeUs;
for (List<Track *>::iterator it = mTracks.begin();
- it != mTracks.end(); ++it, ++id) {
+ it != mTracks.end(); ++it) {
+ minCttsOffsetTimeUs =
+ std::min(minCttsOffsetTimeUs, (*it)->getMinCttsOffsetTimeUs());
+ }
+ ALOGI("Ajust the moov start time from %lld us -> %lld us",
+ (long long)mStartTimestampUs,
+ (long long)(mStartTimestampUs + minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs));
+ // Adjust the global start time.
+ mStartTimestampUs += minCttsOffsetTimeUs - kMaxCttsOffsetTimeUs;
+
+ for (List<Track *>::iterator it = mTracks.begin();
+ it != mTracks.end(); ++it) {
(*it)->writeTrackHeader(mUse32BitOffset);
}
endBox(); // moov
@@ -1626,6 +1641,9 @@
mStssTableEntries(new ListTableEntries<uint32_t, 1>(1000)),
mSttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
mCttsTableEntries(new ListTableEntries<uint32_t, 2>(1000)),
+ mMinCttsOffsetTimeUs(0),
+ mMinCttsOffsetTicks(0),
+ mMaxCttsOffsetTicks(0),
mCodecSpecificData(NULL),
mCodecSpecificDataSize(0),
mGotAllCodecSpecificData(false),
@@ -2814,16 +2832,16 @@
// Update ctts time offset range
if (mStszTableEntries->count() == 0) {
- mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
- mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
+ mMinCttsOffsetTicks = currCttsOffsetTimeTicks;
+ mMaxCttsOffsetTicks = currCttsOffsetTimeTicks;
} else {
- if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
- mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
- } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
- mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
+ if (currCttsOffsetTimeTicks > mMaxCttsOffsetTicks) {
+ mMaxCttsOffsetTicks = currCttsOffsetTimeTicks;
+ } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTicks) {
+ mMinCttsOffsetTicks = currCttsOffsetTimeTicks;
+ mMinCttsOffsetTimeUs = cttsOffsetTimeUs;
}
}
-
}
if (mOwner->isRealTimeRecording()) {
@@ -3164,7 +3182,7 @@
}
int64_t MPEG4Writer::Track::getDurationUs() const {
- return mTrackDurationUs + getStartTimeOffsetScaledTimeUs();
+ return mTrackDurationUs + getStartTimeOffsetTimeUs();
}
int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
@@ -3219,6 +3237,16 @@
mOwner->endBox(); // trak
}
+int64_t MPEG4Writer::Track::getMinCttsOffsetTimeUs() {
+ // For video tracks with ctts table, this should return the minimum ctts
+ // offset in the table. For non-video tracks or video tracks without ctts
+ // table, this will return kMaxCttsOffsetTimeUs.
+ if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) {
+ return kMaxCttsOffsetTimeUs;
+ }
+ return mMinCttsOffsetTimeUs;
+}
+
void MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
mOwner->beginBox("stbl");
mOwner->beginBox("stsd");
@@ -3648,7 +3676,7 @@
mOwner->endBox(); // pasp
}
-int64_t MPEG4Writer::Track::getStartTimeOffsetScaledTimeUs() const {
+int64_t MPEG4Writer::Track::getStartTimeOffsetTimeUs() const {
int64_t trackStartTimeOffsetUs = 0;
int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
if (mStartTimestampUs != -1 && mStartTimestampUs != moovStartTimeUs) {
@@ -3659,23 +3687,30 @@
}
int32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
- return (getStartTimeOffsetScaledTimeUs() * mTimeScale + 500000LL) / 1000000LL;
+ return (getStartTimeOffsetTimeUs() * mTimeScale + 500000LL) / 1000000LL;
}
void MPEG4Writer::Track::writeSttsBox() {
mOwner->beginBox("stts");
mOwner->writeInt32(0); // version=0, flags=0
- uint32_t duration;
- CHECK(mSttsTableEntries->get(duration, 1));
- duration = htonl(duration); // Back to host byte order
- mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
+ if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) {
+ // For non-vdeio tracks or video tracks without ctts table,
+ // adjust duration of first sample for tracks to account for
+ // first sample not starting at the media start time.
+ // TODO: consider signaling this using some offset
+ // as this is not quite correct.
+ uint32_t duration;
+ CHECK(mSttsTableEntries->get(duration, 1));
+ duration = htonl(duration); // Back to host byte order
+ mSttsTableEntries->set(htonl(duration + getStartTimeOffsetScaledTime()), 1);
+ }
mSttsTableEntries->write(mOwner);
mOwner->endBox(); // stts
}
void MPEG4Writer::Track::writeCttsBox() {
// There is no B frame at all
- if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
+ if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) {
return;
}
@@ -3685,11 +3720,12 @@
}
ALOGV("ctts box has %d entries with range [%" PRId64 ", %" PRId64 "]",
- mCttsTableEntries->count(), mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
+ mCttsTableEntries->count(), mMinCttsOffsetTicks, mMaxCttsOffsetTicks);
mOwner->beginBox("ctts");
mOwner->writeInt32(0); // version=0, flags=0
- int64_t delta = mMinCttsOffsetTimeUs - getStartTimeOffsetScaledTime();
+ int64_t deltaTimeUs = kMaxCttsOffsetTimeUs - getStartTimeOffsetTimeUs();
+ int64_t delta = (deltaTimeUs * mTimeScale + 500000LL) / 1000000LL;
mCttsTableEntries->adjustEntries([delta](size_t /* ix */, uint32_t (&value)[2]) {
// entries are <count, ctts> pairs; adjust only ctts
uint32_t duration = htonl(value[1]); // back to host byte order
diff --git a/media/libstagefright/include/media/stagefright/MPEG4Writer.h b/media/libstagefright/include/media/stagefright/MPEG4Writer.h
index 1c4827f..dd357cc 100644
--- a/media/libstagefright/include/media/stagefright/MPEG4Writer.h
+++ b/media/libstagefright/include/media/stagefright/MPEG4Writer.h
@@ -83,6 +83,10 @@
kWhatSwitch = 'swch',
};
+ enum {
+ kMaxCttsOffsetTimeUs = 1000000LL, // 1 second
+ };
+
int mFd;
int mNextFd;
sp<MetaData> mStartMeta;