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
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user