Loading include/media/stagefright/MPEG4Writer.h +6 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading include/media/stagefright/MetaData.h +2 −2 Original line number Diff line number Diff line Loading @@ -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 { Loading media/libstagefright/MPEG4Writer.cpp +65 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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) { Loading @@ -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); Loading Loading @@ -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"); Loading Loading
include/media/stagefright/MPEG4Writer.h +6 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading
include/media/stagefright/MetaData.h +2 −2 Original line number Diff line number Diff line Loading @@ -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 { Loading
media/libstagefright/MPEG4Writer.cpp +65 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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) { Loading @@ -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); Loading Loading @@ -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"); Loading