diff options
-rw-r--r-- | include/media/stagefright/MPEG4Writer.h | 13 | ||||
-rw-r--r-- | media/libstagefright/MPEG4Writer.cpp | 86 |
2 files changed, 57 insertions, 42 deletions
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h index f7618e9..5c5229d 100644 --- a/include/media/stagefright/MPEG4Writer.h +++ b/include/media/stagefright/MPEG4Writer.h @@ -98,6 +98,8 @@ private: List<MediaBuffer *> mSamples; // Sample data // Convenient constructor + Chunk(): mTrack(NULL), mTimeStampUs(0) {} + Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples) : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) { } @@ -124,13 +126,14 @@ private: void bufferChunk(const Chunk& chunk); // Write all buffered chunks from all tracks - void writeChunks(); + void writeAllChunks(); - // Write a chunk if there is one - status_t writeOneChunk(); + // Retrieve the proper chunk to write if there is one + // Return true if a chunk is found; otherwise, return false. + bool findChunkToWrite(Chunk *chunk); - // Write the first chunk from the given ChunkInfo. - void writeFirstChunk(ChunkInfo* info); + // Actually write the given chunk to the file. + void writeChunkToFile(Chunk* chunk); // Adjust other track media clock (presumably wall clock) // based on audio track media clock with the drift time. diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index d1a497f..b11789d 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -1122,41 +1122,41 @@ void MPEG4Writer::bufferChunk(const Chunk& chunk) { CHECK("Received a chunk for a unknown track" == 0); } -void MPEG4Writer::writeFirstChunk(ChunkInfo* info) { - LOGV("writeFirstChunk: %p", info->mTrack); - - List<Chunk>::iterator chunkIt = info->mChunks.begin(); - for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); - it != chunkIt->mSamples.end(); ++it) { - - off64_t offset = info->mTrack->isAvc() - ? addLengthPrefixedSample_l(*it) - : addSample_l(*it); - if (it == chunkIt->mSamples.begin()) { - info->mTrack->addChunkOffset(offset); +void MPEG4Writer::writeChunkToFile(Chunk* chunk) { + LOGV("writeChunkToFile: %lld from %s track", + chunk.mTimestampUs, chunk.mTrack->isAudio()? "audio": "video"); + + int32_t isFirstSample = true; + while (!chunk->mSamples.empty()) { + List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); + + off64_t offset = chunk->mTrack->isAvc() + ? addLengthPrefixedSample_l(*it) + : addSample_l(*it); + + if (isFirstSample) { + chunk->mTrack->addChunkOffset(offset); + isFirstSample = false; } - } - // Done with the current chunk. - // Release all the samples in this chunk. - while (!chunkIt->mSamples.empty()) { - List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); (*it)->release(); (*it) = NULL; - chunkIt->mSamples.erase(it); + chunk->mSamples.erase(it); } - chunkIt->mSamples.clear(); - info->mChunks.erase(chunkIt); + chunk->mSamples.clear(); } -void MPEG4Writer::writeChunks() { - LOGV("writeChunks"); +void MPEG4Writer::writeAllChunks() { + LOGV("writeAllChunks"); size_t outstandingChunks = 0; while (!mChunkInfos.empty()) { List<ChunkInfo>::iterator it = mChunkInfos.begin(); while (!it->mChunks.empty()) { - CHECK_EQ(OK, writeOneChunk()); - ++outstandingChunks; + Chunk chunk; + if (findChunkToWrite(&chunk)) { + writeChunkToFile(&chunk); + ++outstandingChunks; + } } it->mTrack = NULL; mChunkInfos.erase(it); @@ -1165,8 +1165,8 @@ void MPEG4Writer::writeChunks() { LOGD("%d chunks are written in the last batch", outstandingChunks); } -status_t MPEG4Writer::writeOneChunk() { - LOGV("writeOneChunk"); +bool MPEG4Writer::findChunkToWrite(Chunk *chunk) { + LOGV("findChunkToWrite"); // Find the smallest timestamp, and write that chunk out // XXX: What if some track is just too slow? @@ -1185,38 +1185,50 @@ status_t MPEG4Writer::writeOneChunk() { if (track == NULL) { LOGV("Nothing to be written after all"); - return OK; + return false; } if (mIsFirstChunk) { mIsFirstChunk = false; } + for (List<ChunkInfo>::iterator it = mChunkInfos.begin(); it != mChunkInfos.end(); ++it) { if (it->mTrack == track) { - writeFirstChunk(&(*it)); + *chunk = *(it->mChunks.begin()); + it->mChunks.erase(it->mChunks.begin()); + CHECK_EQ(chunk->mTrack, track); + return true; } } - return OK; + + return false; } void MPEG4Writer::threadFunc() { LOGV("threadFunc"); prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0); + + Mutex::Autolock autoLock(mLock); while (!mDone) { - { - Mutex::Autolock autolock(mLock); + Chunk chunk; + bool chunkFound = false; + + while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) { mChunkReadyCondition.wait(mLock); - CHECK_EQ(writeOneChunk(), OK); } - } - { - // Write ALL samples - Mutex::Autolock autolock(mLock); - writeChunks(); + // Actual write without holding the lock in order to + // reduce the blocking time for media track threads. + if (chunkFound) { + mLock.unlock(); + writeChunkToFile(&chunk); + mLock.lock(); + } } + + writeAllChunks(); } status_t MPEG4Writer::startWriterThread() { |