summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/MPEG4Writer.cpp
diff options
context:
space:
mode:
authorJames Dong <jdong@google.com>2010-07-02 11:39:06 -0700
committerJames Dong <jdong@google.com>2010-07-14 17:29:17 -0700
commit8f5f2fcee5c12d08df71d17017410c50951fc2e3 (patch)
tree4cfeb1085495bacbc93775b43e0022fed69ca993 /media/libstagefright/MPEG4Writer.cpp
parent98fe12aba55e8b8bb14b23c4c3cdba9a99a9753c (diff)
downloadframeworks_av-8f5f2fcee5c12d08df71d17017410c50951fc2e3.zip
frameworks_av-8f5f2fcee5c12d08df71d17017410c50951fc2e3.tar.gz
frameworks_av-8f5f2fcee5c12d08df71d17017410c50951fc2e3.tar.bz2
Support user-supplied timescales for authoring
- also, change all the real time unit to microseconds in MPEG4Writer Change-Id: I260f512f2eb670ade7b8858a56335a5d639de756
Diffstat (limited to 'media/libstagefright/MPEG4Writer.cpp')
-rw-r--r--media/libstagefright/MPEG4Writer.cpp102
1 files changed, 63 insertions, 39 deletions
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 6a4a131..b7388bb 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -41,6 +41,7 @@ namespace android {
class MPEG4Writer::Track {
public:
Track(MPEG4Writer *owner, const sp<MediaSource> &source);
+
~Track();
status_t start(MetaData *params);
@@ -61,12 +62,13 @@ private:
volatile bool mResumed;
int64_t mMaxTimeStampUs;
int64_t mEstimatedTrackSizeBytes;
+ int32_t mTimeScale;
pthread_t mThread;
struct SampleInfo {
size_t size;
- int64_t timestamp;
+ int64_t timestampUs;
};
List<SampleInfo> mSampleInfos;
bool mSamplesHaveSameSize;
@@ -92,11 +94,11 @@ private:
struct SttsTableEntry {
- SttsTableEntry(uint32_t count, uint32_t duration)
- : sampleCount(count), sampleDuration(duration) {}
+ SttsTableEntry(uint32_t count, uint32_t durationUs)
+ : sampleCount(count), sampleDurationUs(durationUs) {}
uint32_t sampleCount;
- uint32_t sampleDuration;
+ uint32_t sampleDurationUs;
};
List<SttsTableEntry> mSttsTableEntries;
@@ -270,6 +272,13 @@ status_t MPEG4Writer::start(MetaData *param) {
return OK;
}
+ if (!param ||
+ !param->findInt32(kKeyTimeScale, &mTimeScale)) {
+ mTimeScale = 1000;
+ }
+ CHECK(mTimeScale > 0);
+ LOGV("movie time scale: %d", mTimeScale);
+
mStreamableFile = true;
mWriteMoovBoxToMemory = false;
mMoovBoxBuffer = NULL;
@@ -336,14 +345,14 @@ void MPEG4Writer::stop() {
return;
}
- int64_t max_duration = 0;
+ int64_t maxDurationUs = 0;
for (List<Track *>::iterator it = mTracks.begin();
it != mTracks.end(); ++it) {
(*it)->stop();
- int64_t duration = (*it)->getDurationUs();
- if (duration > max_duration) {
- max_duration = duration;
+ int64_t durationUs = (*it)->getDurationUs();
+ if (durationUs > maxDurationUs) {
+ maxDurationUs = durationUs;
}
}
@@ -367,8 +376,7 @@ void MPEG4Writer::stop() {
mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
mMoovBoxBufferOffset = 0;
CHECK(mMoovBoxBuffer != NULL);
- int32_t timeScale = 1000;
- int32_t duration = max_duration / timeScale;
+ int32_t duration = (maxDurationUs * mTimeScale) / 1E6;
beginBox("moov");
@@ -376,7 +384,7 @@ void MPEG4Writer::stop() {
writeInt32(0); // version=0, flags=0
writeInt32(now); // creation time
writeInt32(now); // modification time
- writeInt32(timeScale); // timescale
+ writeInt32(mTimeScale); // mvhd timescale
writeInt32(duration);
writeInt32(0x10000); // rate: 1.0
writeInt16(0x100); // volume
@@ -655,7 +663,6 @@ void MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
}
int64_t MPEG4Writer::getStartTimestampUs() {
- LOGI("getStartTimestampUs: %lld", mStartTimestampUs);
Mutex::Autolock autoLock(mLock);
return mStartTimestampUs;
}
@@ -683,6 +690,11 @@ MPEG4Writer::Track::Track(
mGotAllCodecSpecificData(false),
mReachedEOS(false) {
getCodecSpecificDataFromInputFormatIfPossible();
+
+ if (!mMeta->findInt32(kKeyTimeScale, &mTimeScale)) {
+ mTimeScale = 1000;
+ }
+ CHECK(mTimeScale > 0);
}
void MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
@@ -927,9 +939,9 @@ void MPEG4Writer::Track::threadEntry() {
int64_t chunkTimestampUs = 0;
int32_t nChunks = 0;
int32_t nZeroLengthFrames = 0;
- int64_t lastTimestamp = 0; // Timestamp of the previous sample
- int64_t lastDuration = 0; // Time spacing between the previous two samples
- int32_t sampleCount = 1; // Sample count in the current stts table entry
+ int64_t lastTimestampUs = 0; // Previous sample time stamp in ms
+ int64_t lastDurationUs = 0; // Between the previous two samples in ms
+ int32_t sampleCount = 1; // Sample count in the current stts table entry
uint32_t previousSampleSize = 0; // Size of the previous sample
int64_t previousPausedDurationUs = 0;
sp<MetaData> meta_data;
@@ -1113,7 +1125,7 @@ void MPEG4Writer::Track::threadEntry() {
}
if (mResumed) {
- previousPausedDurationUs += (timestampUs - mMaxTimeStampUs - 1000 * lastDuration);
+ previousPausedDurationUs += (timestampUs - mMaxTimeStampUs - lastDurationUs);
mResumed = false;
}
@@ -1124,12 +1136,11 @@ void MPEG4Writer::Track::threadEntry() {
mMaxTimeStampUs = timestampUs;
}
- // Our timestamp is in ms.
- info.timestamp = (timestampUs + 500) / 1000;
+ info.timestampUs = timestampUs;
mSampleInfos.push_back(info);
if (mSampleInfos.size() > 2) {
- if (lastDuration != info.timestamp - lastTimestamp) {
- SttsTableEntry sttsEntry(sampleCount, lastDuration);
+ if (lastDurationUs != info.timestampUs - lastTimestampUs) {
+ SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
mSttsTableEntries.push_back(sttsEntry);
sampleCount = 1;
} else {
@@ -1142,8 +1153,8 @@ void MPEG4Writer::Track::threadEntry() {
}
previousSampleSize = info.size;
}
- lastDuration = info.timestamp - lastTimestamp;
- lastTimestamp = info.timestamp;
+ lastDurationUs = info.timestampUs - lastTimestampUs;
+ lastTimestampUs = info.timestampUs;
if (isSync != 0) {
mStssTableEntries.push_back(mSampleInfos.size());
@@ -1213,11 +1224,11 @@ void MPEG4Writer::Track::threadEntry() {
// there is no frame time after it, just repeat the previous
// frame's duration.
if (mSampleInfos.size() == 1) {
- lastDuration = 0; // A single sample's duration
+ lastDurationUs = 0; // A single sample's duration
} else {
++sampleCount; // Count for the last sample
}
- SttsTableEntry sttsEntry(sampleCount, lastDuration);
+ SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
mSttsTableEntries.push_back(sttsEntry);
mReachedEOS = true;
LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames - %s",
@@ -1249,12 +1260,13 @@ void MPEG4Writer::Track::trackProgressStatus(int32_t nFrames, int64_t timeUs) {
void MPEG4Writer::Track::findMinAvgMaxSampleDurationMs(
int32_t *min, int32_t *avg, int32_t *max) {
CHECK(!mSampleInfos.empty());
- int32_t avgSampleDurationMs = mMaxTimeStampUs / 1000/ mSampleInfos.size();
+ int32_t avgSampleDurationMs = mMaxTimeStampUs / 1000 / mSampleInfos.size();
int32_t minSampleDurationMs = 0x7FFFFFFF;
int32_t maxSampleDurationMs = 0;
for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
it != mSttsTableEntries.end(); ++it) {
- int32_t sampleDurationMs = static_cast<int32_t>(it->sampleDuration);
+ int32_t sampleDurationMs =
+ (static_cast<int32_t>(it->sampleDurationUs) + 500) / 1000;
if (sampleDurationMs > maxSampleDurationMs) {
maxSampleDurationMs = sampleDurationMs;
} else if (sampleDurationMs < minSampleDurationMs) {
@@ -1370,10 +1382,13 @@ void MPEG4Writer::Track::writeTrackHeader(
CHECK(success);
bool is_audio = !strncasecmp(mime, "audio/", 6);
- int32_t timeScale = 1000;
- int32_t duration = getDurationUs() / timeScale;
+ LOGV("%s track time scale: %d",
+ is_audio? "Audio": "Video", mTimeScale);
+
time_t now = time(NULL);
+ int32_t mvhdTimeScale = mOwner->getTimeScale();
+ int64_t trakDurationUs = getDurationUs();
mOwner->beginBox("trak");
@@ -1385,7 +1400,9 @@ void MPEG4Writer::Track::writeTrackHeader(
mOwner->writeInt32(now); // modification time
mOwner->writeInt32(trackID);
mOwner->writeInt32(0); // reserved
- mOwner->writeInt32(duration);
+ int32_t tkhdDuration =
+ (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
+ mOwner->writeInt32(tkhdDuration); // in mvhd timescale
mOwner->writeInt32(0); // reserved
mOwner->writeInt32(0); // reserved
mOwner->writeInt16(0); // layer
@@ -1423,12 +1440,17 @@ void MPEG4Writer::Track::writeTrackHeader(
mOwner->beginBox("elst");
mOwner->writeInt32(0); // version=0, flags=0: 32-bit time
mOwner->writeInt32(2); // never ends with an empty list
- int64_t durationMs =
- (mStartTimestampUs - moovStartTimeUs) / 1000;
- mOwner->writeInt32(durationMs); // edit duration
- mOwner->writeInt32(-1); // empty edit box to signal starting time offset
- mOwner->writeInt32(1 << 16); // x1 rate
- mOwner->writeInt32(duration);
+
+ // First elst entry: specify the starting time offset
+ int64_t offsetUs = mStartTimestampUs - moovStartTimeUs;
+ 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();
@@ -1441,8 +1463,9 @@ void MPEG4Writer::Track::writeTrackHeader(
mOwner->writeInt32(0); // version=0, flags=0
mOwner->writeInt32(now); // creation time
mOwner->writeInt32(now); // modification time
- mOwner->writeInt32(timeScale); // timescale
- mOwner->writeInt32(duration); // duration
+ mOwner->writeInt32(mTimeScale); // media timescale
+ int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
+ mOwner->writeInt32(mdhdDuration); // use media timescale
// Language follows the three letter standard ISO-639-2/T
// 'e', 'n', 'g' for "English", for instance.
// Each character is packed as the difference between its ASCII value and 0x60.
@@ -1664,7 +1687,8 @@ void MPEG4Writer::Track::writeTrackHeader(
for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
it != mSttsTableEntries.end(); ++it) {
mOwner->writeInt32(it->sampleCount);
- mOwner->writeInt32(it->sampleDuration);
+ int32_t dur = (it->sampleDurationUs * mTimeScale + 5E5) / 1E6;
+ mOwner->writeInt32(dur);
}
mOwner->endBox(); // stts
@@ -1717,7 +1741,7 @@ void MPEG4Writer::Track::writeTrackHeader(
mOwner->writeInt64((*it));
}
}
- mOwner->endBox(); // co64
+ mOwner->endBox(); // stco or co64
mOwner->endBox(); // stbl
mOwner->endBox(); // minf