MPEG4Writer.h revision bc07bcc65e91c7aea9713631ae67760dcf1b0286
104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov/* 204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * Copyright (C) 2009 The Android Open Source Project 304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * 404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License"); 504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * you may not use this file except in compliance with the License. 604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * You may obtain a copy of the License at 704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * 804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * http://www.apache.org/licenses/LICENSE-2.0 904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * 1004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * Unless required by applicable law or agreed to in writing, software 1104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS, 1204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * See the License for the specific language governing permissions and 1404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov * limitations under the License. 1504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov */ 1604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 1704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov#ifndef MPEG4_WRITER_H_ 1804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 1904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov#define MPEG4_WRITER_H_ 2004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 2104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov#include <stdio.h> 2204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 2304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov#include <media/stagefright/MediaWriter.h> 2404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov#include <utils/List.h> 2504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov#include <utils/threads.h> 2604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 2704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovnamespace android { 2804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 2904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovclass MediaBuffer; 3004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovclass MediaSource; 3104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovclass MetaData; 3204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 3304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovclass MPEG4Writer : public MediaWriter { 3404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovpublic: 3504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov MPEG4Writer(const char *filename); 3604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov MPEG4Writer(int fd); 3704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 3874c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov virtual status_t addSource(const sp<MediaSource> &source); 3904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov virtual status_t start(MetaData *param = NULL); 4004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov virtual status_t stop(); 4174c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov virtual status_t pause(); 4204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov virtual bool reachedEOS(); 4304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov virtual status_t dump(int fd, const Vector<String16>& args); 4404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 4504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov void beginBox(const char *fourcc); 4604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov void writeInt8(int8_t x); 4704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov void writeInt16(int16_t x); 4804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov void writeInt32(int32_t x); 4904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov void writeInt64(int64_t x); 5004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov void writeCString(const char *s); 5104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov void writeFourcc(const char *fourcc); 5204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov void write(const void *data, size_t size); 5304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov void endBox(); 5404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov uint32_t interleaveDuration() const { return mInterleaveDurationUs; } 5504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov status_t setInterleaveDuration(uint32_t duration); 5604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov int32_t getTimeScale() const { return mTimeScale; } 5704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 5804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovprotected: 5904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov virtual ~MPEG4Writer(); 6004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 6104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganovprivate: 6204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov class Track; 6304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 6404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov int mFd; 6504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov status_t mInitCheck; 6604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov bool mUse4ByteNalLength; 6704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov bool mUse32BitOffset; 6804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov bool mIsFileSizeLimitExplicitlyRequested; 6904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov bool mPaused; 7004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov bool mStarted; 7104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov off64_t mOffset; 7204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov off_t mMdatOffset; 7304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov uint8_t *mMoovBoxBuffer; 7404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov off64_t mMoovBoxBufferOffset; 7504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov bool mWriteMoovBoxToMemory; 7604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov off64_t mFreeBoxOffset; 7704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov bool mStreamableFile; 7804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov off64_t mEstimatedMoovBoxSize; 7904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov uint32_t mInterleaveDurationUs; 8004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov int32_t mTimeScale; 8104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov int64_t mStartTimestampUs; 8204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 8304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov Mutex mLock; 8404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 8504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov List<Track *> mTracks; 8604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 8704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov List<off64_t> mBoxes; 8804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 8904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov void setStartTimestampUs(int64_t timeUs); 9004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov int64_t getStartTimestampUs(); // Not const 9104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov status_t startTracks(MetaData *params); 9204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov size_t numTracks(); 9304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov int64_t estimateMoovBoxSize(int32_t bitRate); 9404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 9504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov struct Chunk { 9604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov Track *mTrack; // Owner 9704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov int64_t mTimeStampUs; // Timestamp of the 1st sample 9804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov List<MediaBuffer *> mSamples; // Sample data 9904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 10004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov // Convenient constructor 10104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov Chunk(): mTrack(NULL), mTimeStampUs(0) {} 10204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 10304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples) 10404df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) { 10504df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov } 10604df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov 10704df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov }; 10804df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov struct ChunkInfo { 10904df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov Track *mTrack; // Owner 11004df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov List<Chunk> mChunks; // Remaining chunks to be written 11104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov }; 11274c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov 11374c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov bool mIsFirstChunk; 11474c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov volatile bool mDone; // Writer thread is done? 11574c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov pthread_t mThread; // Thread id for the writer 11674c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov List<ChunkInfo> mChunkInfos; // Chunk infos 11774c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov Condition mChunkReadyCondition; // Signal that chunks are available 11874c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov 11974c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov // Writer thread handling 12074c9983e80d8224bbe1de7c37e8f6ac4a76df11dSvetoslav Ganov status_t startWriterThread(); 12104df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov void stopWriterThread(); 12204df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov static void *ThreadWrapper(void *me); 12304df738bcb6584dd82b731a67f4cf8d6925b061eSvetoslav Ganov void threadFunc(); 124 125 // Buffer a single chunk to be written out later. 126 void bufferChunk(const Chunk& chunk); 127 128 // Write all buffered chunks from all tracks 129 void writeAllChunks(); 130 131 // Retrieve the proper chunk to write if there is one 132 // Return true if a chunk is found; otherwise, return false. 133 bool findChunkToWrite(Chunk *chunk); 134 135 // Actually write the given chunk to the file. 136 void writeChunkToFile(Chunk* chunk); 137 138 // Adjust other track media clock (presumably wall clock) 139 // based on audio track media clock with the drift time. 140 int64_t mDriftTimeUs; 141 void setDriftTimeUs(int64_t driftTimeUs); 142 int64_t getDriftTimeUs(); 143 144 // Return whether the nal length is 4 bytes or 2 bytes 145 // Only makes sense for H.264/AVC 146 bool useNalLengthFour(); 147 148 void lock(); 149 void unlock(); 150 151 // Acquire lock before calling these methods 152 off64_t addSample_l(MediaBuffer *buffer); 153 off64_t addLengthPrefixedSample_l(MediaBuffer *buffer); 154 155 inline size_t write(const void *ptr, size_t size, size_t nmemb); 156 bool exceedsFileSizeLimit(); 157 bool use32BitFileOffset() const; 158 bool exceedsFileDurationLimit(); 159 bool isFileStreamable() const; 160 void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK); 161 void writeCompositionMatrix(int32_t degrees); 162 163 MPEG4Writer(const MPEG4Writer &); 164 MPEG4Writer &operator=(const MPEG4Writer &); 165}; 166 167} // namespace android 168 169#endif // MPEG4_WRITER_H_ 170