1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef MPEG4_WRITER_H_ 18 19 #define MPEG4_WRITER_H_ 20 21 #include <stdio.h> 22 23 #include <media/IMediaSource.h> 24 #include <media/stagefright/MediaWriter.h> 25 #include <utils/List.h> 26 #include <utils/threads.h> 27 28 namespace android { 29 30 class AMessage; 31 class MediaBuffer; 32 class MetaData; 33 34 class MPEG4Writer : public MediaWriter { 35 public: 36 MPEG4Writer(int fd); 37 38 // Limitations 39 // 1. No more than 2 tracks can be added 40 // 2. Only video or audio source can be added 41 // 3. No more than one video and/or one audio source can be added. 42 virtual status_t addSource(const sp<IMediaSource> &source); 43 44 // Returns INVALID_OPERATION if there is no source or track. 45 virtual status_t start(MetaData *param = NULL); stop()46 virtual status_t stop() { return reset(); } 47 virtual status_t pause(); 48 virtual bool reachedEOS(); 49 virtual status_t dump(int fd, const Vector<String16>& args); 50 51 void beginBox(const char *fourcc); 52 void beginBox(uint32_t id); 53 void writeInt8(int8_t x); 54 void writeInt16(int16_t x); 55 void writeInt32(int32_t x); 56 void writeInt64(int64_t x); 57 void writeCString(const char *s); 58 void writeFourcc(const char *fourcc); 59 void write(const void *data, size_t size); 60 inline size_t write(const void *ptr, size_t size, size_t nmemb); 61 void endBox(); interleaveDuration()62 uint32_t interleaveDuration() const { return mInterleaveDurationUs; } 63 status_t setInterleaveDuration(uint32_t duration); getTimeScale()64 int32_t getTimeScale() const { return mTimeScale; } 65 66 status_t setGeoData(int latitudex10000, int longitudex10000); 67 status_t setCaptureRate(float captureFps); setStartTimeOffsetMs(int ms)68 virtual void setStartTimeOffsetMs(int ms) { mStartTimeOffsetMs = ms; } getStartTimeOffsetMs()69 virtual int32_t getStartTimeOffsetMs() const { return mStartTimeOffsetMs; } 70 71 protected: 72 virtual ~MPEG4Writer(); 73 74 private: 75 class Track; 76 77 int mFd; 78 status_t mInitCheck; 79 bool mIsRealTimeRecording; 80 bool mUse4ByteNalLength; 81 bool mUse32BitOffset; 82 bool mIsFileSizeLimitExplicitlyRequested; 83 bool mPaused; 84 bool mStarted; // Writer thread + track threads started successfully 85 bool mWriterThreadStarted; // Only writer thread started successfully 86 off64_t mOffset; 87 off_t mMdatOffset; 88 uint8_t *mMoovBoxBuffer; 89 off64_t mMoovBoxBufferOffset; 90 bool mWriteMoovBoxToMemory; 91 off64_t mFreeBoxOffset; 92 bool mStreamableFile; 93 off64_t mEstimatedMoovBoxSize; 94 off64_t mMoovExtraSize; 95 uint32_t mInterleaveDurationUs; 96 int32_t mTimeScale; 97 int64_t mStartTimestampUs; 98 int mLatitudex10000; 99 int mLongitudex10000; 100 bool mAreGeoTagsAvailable; 101 int32_t mStartTimeOffsetMs; 102 103 Mutex mLock; 104 105 List<Track *> mTracks; 106 107 List<off64_t> mBoxes; 108 109 sp<AMessage> mMetaKeys; 110 111 void setStartTimestampUs(int64_t timeUs); 112 int64_t getStartTimestampUs(); // Not const 113 status_t startTracks(MetaData *params); 114 size_t numTracks(); 115 int64_t estimateMoovBoxSize(int32_t bitRate); 116 117 struct Chunk { 118 Track *mTrack; // Owner 119 int64_t mTimeStampUs; // Timestamp of the 1st sample 120 List<MediaBuffer *> mSamples; // Sample data 121 122 // Convenient constructor ChunkChunk123 Chunk(): mTrack(NULL), mTimeStampUs(0) {} 124 ChunkChunk125 Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples) 126 : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) { 127 } 128 129 }; 130 struct ChunkInfo { 131 Track *mTrack; // Owner 132 List<Chunk> mChunks; // Remaining chunks to be written 133 134 // Previous chunk timestamp that has been written 135 int64_t mPrevChunkTimestampUs; 136 137 // Max time interval between neighboring chunks 138 int64_t mMaxInterChunkDurUs; 139 140 }; 141 142 bool mIsFirstChunk; 143 volatile bool mDone; // Writer thread is done? 144 pthread_t mThread; // Thread id for the writer 145 List<ChunkInfo> mChunkInfos; // Chunk infos 146 Condition mChunkReadyCondition; // Signal that chunks are available 147 148 // Writer thread handling 149 status_t startWriterThread(); 150 void stopWriterThread(); 151 static void *ThreadWrapper(void *me); 152 void threadFunc(); 153 154 // Buffer a single chunk to be written out later. 155 void bufferChunk(const Chunk& chunk); 156 157 // Write all buffered chunks from all tracks 158 void writeAllChunks(); 159 160 // Retrieve the proper chunk to write if there is one 161 // Return true if a chunk is found; otherwise, return false. 162 bool findChunkToWrite(Chunk *chunk); 163 164 // Actually write the given chunk to the file. 165 void writeChunkToFile(Chunk* chunk); 166 167 // Adjust other track media clock (presumably wall clock) 168 // based on audio track media clock with the drift time. 169 int64_t mDriftTimeUs; 170 void setDriftTimeUs(int64_t driftTimeUs); 171 int64_t getDriftTimeUs(); 172 173 // Return whether the nal length is 4 bytes or 2 bytes 174 // Only makes sense for H.264/AVC 175 bool useNalLengthFour(); 176 177 // Return whether the writer is used for real time recording. 178 // In real time recording mode, new samples will be allowed to buffered into 179 // chunks in higher priority thread, even though the file writer has not 180 // drained the chunks yet. 181 // By default, real time recording is on. 182 bool isRealTimeRecording() const; 183 184 void lock(); 185 void unlock(); 186 187 // Acquire lock before calling these methods 188 off64_t addSample_l(MediaBuffer *buffer); 189 off64_t addLengthPrefixedSample_l(MediaBuffer *buffer); 190 191 bool exceedsFileSizeLimit(); 192 bool use32BitFileOffset() const; 193 bool exceedsFileDurationLimit(); 194 bool isFileStreamable() const; 195 void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK); 196 void writeCompositionMatrix(int32_t degrees); 197 void writeMvhdBox(int64_t durationUs); 198 void writeMoovBox(int64_t durationUs); 199 void writeFtypBox(MetaData *param); 200 void writeUdtaBox(); 201 void writeGeoDataBox(); 202 void writeLatitude(int degreex10000); 203 void writeLongitude(int degreex10000); 204 205 void addDeviceMeta(); 206 void writeHdlr(); 207 void writeKeys(); 208 void writeIlst(); 209 void writeMetaBox(); 210 void sendSessionSummary(); 211 void release(); 212 status_t reset(); 213 214 static uint32_t getMpeg4Time(); 215 216 MPEG4Writer(const MPEG4Writer &); 217 MPEG4Writer &operator=(const MPEG4Writer &); 218 }; 219 220 } // namespace android 221 222 #endif // MPEG4_WRITER_H_ 223