summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/MPEG4Writer.cpp
diff options
context:
space:
mode:
authorJames Dong <jdong@google.com>2010-04-20 11:50:11 -0700
committerJames Dong <jdong@google.com>2010-05-06 14:55:33 -0700
commitbe83c9e8c71ce16c0d0e9ed9df525510a49a541b (patch)
treec750338bd885690d1d7dd67af96ea3f70ae21eaf /media/libstagefright/MPEG4Writer.cpp
parentd8a30349da270715156d3f658b165481ce10cf71 (diff)
downloadframeworks_av-be83c9e8c71ce16c0d0e9ed9df525510a49a541b.zip
frameworks_av-be83c9e8c71ce16c0d0e9ed9df525510a49a541b.tar.gz
frameworks_av-be83c9e8c71ce16c0d0e9ed9df525510a49a541b.tar.bz2
Metadata construction optimization
- Potentially much shorter stts box if samples have roughly the same duration - Potentially much shorter stsz box if all samples have the same size Change-Id: I4f7663dd64285070995585a02bb3ba1e1049a0cf
Diffstat (limited to 'media/libstagefright/MPEG4Writer.cpp')
-rw-r--r--media/libstagefright/MPEG4Writer.cpp103
1 files changed, 65 insertions, 38 deletions
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 29ec876..fd792ee 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -60,6 +60,8 @@ private:
int64_t timestamp;
};
List<SampleInfo> mSampleInfos;
+ bool mSamplesHaveSameSize;
+
List<MediaBuffer *> mChunkSamples;
List<off_t> mChunkOffsets;
@@ -78,6 +80,16 @@ private:
List<int32_t> mStssTableEntries;
+ struct SttsTableEntry {
+
+ SttsTableEntry(uint32_t count, uint32_t duration)
+ : sampleCount(count), sampleDuration(duration) {}
+
+ uint32_t sampleCount;
+ uint32_t sampleDuration;
+ };
+ List<SttsTableEntry> mSttsTableEntries;
+
void *mCodecSpecificData;
size_t mCodecSpecificDataSize;
bool mGotAllCodecSpecificData;
@@ -389,6 +401,7 @@ MPEG4Writer::Track::Track(
mSource(source),
mDone(false),
mMaxTimeStampUs(0),
+ mSamplesHaveSameSize(true),
mCodecSpecificData(NULL),
mCodecSpecificDataSize(0),
mGotAllCodecSpecificData(false),
@@ -562,6 +575,10 @@ 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
+ uint32_t previousSampleSize = 0; // Size of the previous sample
MediaBuffer *buffer;
while (!mDone && mSource->read(&buffer) == OK) {
@@ -584,11 +601,7 @@ void MPEG4Writer::Track::threadEntry() {
(const uint8_t *)buffer->data()
+ buffer->range_offset(),
buffer->range_length());
-
- if (err != OK) {
- LOGE("failed to parse avc codec specific data.");
- break;
- }
+ CHECK_EQ(OK, err);
} else if (is_mpeg4) {
mCodecSpecificDataSize = buffer->range_length();
mCodecSpecificData = malloc(mCodecSpecificDataSize);
@@ -676,14 +689,9 @@ void MPEG4Writer::Track::threadEntry() {
status_t err = makeAVCCodecSpecificData(
(const uint8_t *)tmp, size);
-
free(tmp);
tmp = NULL;
-
- if (err != OK) {
- LOGE("failed to parse avc codec specific data.");
- break;
- }
+ CHECK_EQ(OK, err);
mGotAllCodecSpecificData = true;
}
@@ -712,6 +720,23 @@ void MPEG4Writer::Track::threadEntry() {
// Our timestamp is in ms.
info.timestamp = (timestampUs + 500) / 1000;
mSampleInfos.push_back(info);
+ if (mSampleInfos.size() > 2) {
+ if (lastDuration != info.timestamp - lastTimestamp) {
+ SttsTableEntry sttsEntry(sampleCount, lastDuration);
+ mSttsTableEntries.push_back(sttsEntry);
+ sampleCount = 1;
+ } else {
+ ++sampleCount;
+ }
+ }
+ if (mSamplesHaveSameSize) {
+ if (mSampleInfos.size() >= 2 && previousSampleSize != info.size) {
+ mSamplesHaveSameSize = false;
+ }
+ previousSampleSize = info.size;
+ }
+ lastDuration = info.timestamp - lastTimestamp;
+ lastTimestamp = info.timestamp;
////////////////////////////////////////////////////////////////////////////////
// Make a deep copy of the MediaBuffer less Metadata
@@ -749,11 +774,13 @@ void MPEG4Writer::Track::threadEntry() {
isSync != 0) {
mStssTableEntries.push_back(mSampleInfos.size());
}
- // Our timestamp is in ms.
+
buffer->release();
buffer = NULL;
}
+ CHECK(!mSampleInfos.empty());
+
// Last chunk
if (!mChunkSamples.empty()) {
++nChunks;
@@ -762,6 +789,16 @@ void MPEG4Writer::Track::threadEntry() {
writeOneChunk(is_avc);
}
+ // We don't really know how long the last frame lasts, since
+ // 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
+ } else {
+ ++sampleCount; // Count for the last sample
+ }
+ SttsTableEntry sttsEntry(sampleCount, lastDuration);
+ mSttsTableEntries.push_back(sttsEntry);
mReachedEOS = true;
LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames",
count, nZeroLengthFrames, mSampleInfos.size());
@@ -1054,29 +1091,12 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
mOwner->beginBox("stts");
mOwner->writeInt32(0); // version=0, flags=0
- mOwner->writeInt32(mSampleInfos.size());
-
- List<SampleInfo>::iterator it = mSampleInfos.begin();
- int64_t last = (*it).timestamp;
- int64_t lastDuration = 1;
-
- ++it;
- while (it != mSampleInfos.end()) {
- mOwner->writeInt32(1);
- lastDuration = (*it).timestamp - last;
- mOwner->writeInt32(lastDuration);
-
- last = (*it).timestamp;
-
- ++it;
+ mOwner->writeInt32(mSttsTableEntries.size());
+ for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
+ it != mSttsTableEntries.end(); ++it) {
+ mOwner->writeInt32(it->sampleCount);
+ mOwner->writeInt32(it->sampleDuration);
}
-
- // We don't really know how long the last frame lasts, since
- // there is no frame time after it, just repeat the previous
- // frame's duration.
- mOwner->writeInt32(1);
- mOwner->writeInt32(lastDuration);
-
mOwner->endBox(); // stts
if (!is_audio) {
@@ -1092,11 +1112,18 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
mOwner->beginBox("stsz");
mOwner->writeInt32(0); // version=0, flags=0
- mOwner->writeInt32(0); // default sample size
+ if (mSamplesHaveSameSize) {
+ List<SampleInfo>::iterator it = mSampleInfos.begin();
+ mOwner->writeInt32(it->size); // default sample size
+ } else {
+ mOwner->writeInt32(0);
+ }
mOwner->writeInt32(mSampleInfos.size());
- for (List<SampleInfo>::iterator it = mSampleInfos.begin();
- it != mSampleInfos.end(); ++it) {
- mOwner->writeInt32((*it).size);
+ if (!mSamplesHaveSameSize) {
+ for (List<SampleInfo>::iterator it = mSampleInfos.begin();
+ it != mSampleInfos.end(); ++it) {
+ mOwner->writeInt32((*it).size);
+ }
}
mOwner->endBox(); // stsz