Loading include/media/stagefright/MPEG4Writer.h +8 −5 Original line number Diff line number Diff line Loading @@ -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) { } Loading @@ -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. Loading media/libstagefright/MPEG4Writer.cpp +49 −37 Original line number Diff line number Diff line Loading @@ -1122,42 +1122,42 @@ 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); void MPEG4Writer::writeChunkToFile(Chunk* chunk) { LOGV("writeChunkToFile: %lld from %s track", chunk.mTimestampUs, chunk.mTrack->isAudio()? "audio": "video"); List<Chunk>::iterator chunkIt = info->mChunks.begin(); for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); it != chunkIt->mSamples.end(); ++it) { int32_t isFirstSample = true; while (!chunk->mSamples.empty()) { List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); off64_t offset = info->mTrack->isAvc() off64_t offset = chunk->mTrack->isAvc() ? addLengthPrefixedSample_l(*it) : addSample_l(*it); if (it == chunkIt->mSamples.begin()) { info->mTrack->addChunkOffset(offset); } 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()); Chunk chunk; if (findChunkToWrite(&chunk)) { writeChunkToFile(&chunk); ++outstandingChunks; } } it->mTrack = NULL; mChunkInfos.erase(it); } Loading @@ -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? Loading @@ -1185,40 +1185,52 @@ 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() { LOGV("startWriterThread"); Loading Loading
include/media/stagefright/MPEG4Writer.h +8 −5 Original line number Diff line number Diff line Loading @@ -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) { } Loading @@ -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. Loading
media/libstagefright/MPEG4Writer.cpp +49 −37 Original line number Diff line number Diff line Loading @@ -1122,42 +1122,42 @@ 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); void MPEG4Writer::writeChunkToFile(Chunk* chunk) { LOGV("writeChunkToFile: %lld from %s track", chunk.mTimestampUs, chunk.mTrack->isAudio()? "audio": "video"); List<Chunk>::iterator chunkIt = info->mChunks.begin(); for (List<MediaBuffer *>::iterator it = chunkIt->mSamples.begin(); it != chunkIt->mSamples.end(); ++it) { int32_t isFirstSample = true; while (!chunk->mSamples.empty()) { List<MediaBuffer *>::iterator it = chunk->mSamples.begin(); off64_t offset = info->mTrack->isAvc() off64_t offset = chunk->mTrack->isAvc() ? addLengthPrefixedSample_l(*it) : addSample_l(*it); if (it == chunkIt->mSamples.begin()) { info->mTrack->addChunkOffset(offset); } 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()); Chunk chunk; if (findChunkToWrite(&chunk)) { writeChunkToFile(&chunk); ++outstandingChunks; } } it->mTrack = NULL; mChunkInfos.erase(it); } Loading @@ -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? Loading @@ -1185,40 +1185,52 @@ 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() { LOGV("startWriterThread"); Loading