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#include <media/stagefright/foundation/AHandlerReflector.h> 28#include <media/stagefright/foundation/ALooper.h> 29 30namespace android { 31 32struct AMessage; 33class MediaBuffer; 34class MetaData; 35 36class MPEG4Writer : public MediaWriter { 37public: 38 MPEG4Writer(int fd); 39 40 // Limitations 41 // No more than one video and/or one audio source can be added, but 42 // multiple metadata sources can be added. 43 virtual status_t addSource(const sp<IMediaSource> &source); 44 45 // Returns INVALID_OPERATION if there is no source or track. 46 virtual status_t start(MetaData *param = NULL); 47 virtual status_t stop() { return reset(); } 48 virtual status_t pause(); 49 virtual bool reachedEOS(); 50 virtual status_t dump(int fd, const Vector<String16>& args); 51 52 void beginBox(const char *fourcc); 53 void beginBox(uint32_t id); 54 void writeInt8(int8_t x); 55 void writeInt16(int16_t x); 56 void writeInt32(int32_t x); 57 void writeInt64(int64_t x); 58 void writeCString(const char *s); 59 void writeFourcc(const char *fourcc); 60 void write(const void *data, size_t size); 61 inline size_t write(const void *ptr, size_t size, size_t nmemb); 62 void endBox(); 63 uint32_t interleaveDuration() const { return mInterleaveDurationUs; } 64 status_t setInterleaveDuration(uint32_t duration); 65 int32_t getTimeScale() const { return mTimeScale; } 66 67 status_t setGeoData(int latitudex10000, int longitudex10000); 68 status_t setCaptureRate(float captureFps); 69 status_t setTemporalLayerCount(uint32_t layerCount); 70 void notifyApproachingLimit(); 71 virtual void setStartTimeOffsetMs(int ms) { mStartTimeOffsetMs = ms; } 72 virtual int32_t getStartTimeOffsetMs() const { return mStartTimeOffsetMs; } 73 virtual status_t setNextFd(int fd); 74 75protected: 76 virtual ~MPEG4Writer(); 77 78private: 79 class Track; 80 friend struct AHandlerReflector<MPEG4Writer>; 81 82 enum { 83 kWhatSwitch = 'swch', 84 }; 85 86 enum { 87 kMaxCttsOffsetTimeUs = 1000000LL, // 1 second 88 }; 89 90 int mFd; 91 int mNextFd; 92 sp<MetaData> mStartMeta; 93 status_t mInitCheck; 94 bool mIsRealTimeRecording; 95 bool mUse4ByteNalLength; 96 bool mUse32BitOffset; 97 bool mIsFileSizeLimitExplicitlyRequested; 98 bool mPaused; 99 bool mStarted; // Writer thread + track threads started successfully 100 bool mWriterThreadStarted; // Only writer thread started successfully 101 bool mSendNotify; 102 off64_t mOffset; 103 off_t mMdatOffset; 104 uint8_t *mMoovBoxBuffer; 105 off64_t mMoovBoxBufferOffset; 106 bool mWriteMoovBoxToMemory; 107 off64_t mFreeBoxOffset; 108 bool mStreamableFile; 109 off64_t mEstimatedMoovBoxSize; 110 off64_t mMoovExtraSize; 111 uint32_t mInterleaveDurationUs; 112 int32_t mTimeScale; 113 int64_t mStartTimestampUs; 114 int mLatitudex10000; 115 int mLongitudex10000; 116 bool mAreGeoTagsAvailable; 117 int32_t mStartTimeOffsetMs; 118 bool mSwitchPending; 119 120 sp<ALooper> mLooper; 121 sp<AHandlerReflector<MPEG4Writer> > mReflector; 122 123 Mutex mLock; 124 125 List<Track *> mTracks; 126 127 List<off64_t> mBoxes; 128 129 sp<AMessage> mMetaKeys; 130 131 void setStartTimestampUs(int64_t timeUs); 132 int64_t getStartTimestampUs(); // Not const 133 status_t startTracks(MetaData *params); 134 size_t numTracks(); 135 int64_t estimateMoovBoxSize(int32_t bitRate); 136 137 struct Chunk { 138 Track *mTrack; // Owner 139 int64_t mTimeStampUs; // Timestamp of the 1st sample 140 List<MediaBuffer *> mSamples; // Sample data 141 142 // Convenient constructor 143 Chunk(): mTrack(NULL), mTimeStampUs(0) {} 144 145 Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples) 146 : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) { 147 } 148 149 }; 150 struct ChunkInfo { 151 Track *mTrack; // Owner 152 List<Chunk> mChunks; // Remaining chunks to be written 153 154 // Previous chunk timestamp that has been written 155 int64_t mPrevChunkTimestampUs; 156 157 // Max time interval between neighboring chunks 158 int64_t mMaxInterChunkDurUs; 159 160 }; 161 162 bool mIsFirstChunk; 163 volatile bool mDone; // Writer thread is done? 164 pthread_t mThread; // Thread id for the writer 165 List<ChunkInfo> mChunkInfos; // Chunk infos 166 Condition mChunkReadyCondition; // Signal that chunks are available 167 168 // Writer thread handling 169 status_t startWriterThread(); 170 void stopWriterThread(); 171 static void *ThreadWrapper(void *me); 172 void threadFunc(); 173 174 // Buffer a single chunk to be written out later. 175 void bufferChunk(const Chunk& chunk); 176 177 // Write all buffered chunks from all tracks 178 void writeAllChunks(); 179 180 // Retrieve the proper chunk to write if there is one 181 // Return true if a chunk is found; otherwise, return false. 182 bool findChunkToWrite(Chunk *chunk); 183 184 // Actually write the given chunk to the file. 185 void writeChunkToFile(Chunk* chunk); 186 187 // Adjust other track media clock (presumably wall clock) 188 // based on audio track media clock with the drift time. 189 int64_t mDriftTimeUs; 190 void setDriftTimeUs(int64_t driftTimeUs); 191 int64_t getDriftTimeUs(); 192 193 // Return whether the nal length is 4 bytes or 2 bytes 194 // Only makes sense for H.264/AVC 195 bool useNalLengthFour(); 196 197 // Return whether the writer is used for real time recording. 198 // In real time recording mode, new samples will be allowed to buffered into 199 // chunks in higher priority thread, even though the file writer has not 200 // drained the chunks yet. 201 // By default, real time recording is on. 202 bool isRealTimeRecording() const; 203 204 void lock(); 205 void unlock(); 206 207 // Init all the internal variables for each recording session. Some variables 208 // will only need to be set for the first recording session and they will stay 209 // the same across all the recording sessions. 210 void initInternal(int fd, bool isFirstSession); 211 212 // Acquire lock before calling these methods 213 off64_t addSample_l(MediaBuffer *buffer); 214 off64_t addLengthPrefixedSample_l(MediaBuffer *buffer); 215 off64_t addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer); 216 217 bool exceedsFileSizeLimit(); 218 bool use32BitFileOffset() const; 219 bool exceedsFileDurationLimit(); 220 bool approachingFileSizeLimit(); 221 bool isFileStreamable() const; 222 void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK); 223 void writeCompositionMatrix(int32_t degrees); 224 void writeMvhdBox(int64_t durationUs); 225 void writeMoovBox(int64_t durationUs); 226 void writeFtypBox(MetaData *param); 227 void writeUdtaBox(); 228 void writeGeoDataBox(); 229 void writeLatitude(int degreex10000); 230 void writeLongitude(int degreex10000); 231 void finishCurrentSession(); 232 233 void addDeviceMeta(); 234 void writeHdlr(); 235 void writeKeys(); 236 void writeIlst(); 237 void writeMetaBox(); 238 void sendSessionSummary(); 239 void release(); 240 status_t switchFd(); 241 status_t reset(bool stopSource = true); 242 243 static uint32_t getMpeg4Time(); 244 245 void onMessageReceived(const sp<AMessage> &msg); 246 247 MPEG4Writer(const MPEG4Writer &); 248 MPEG4Writer &operator=(const MPEG4Writer &); 249}; 250 251} // namespace android 252 253#endif // MPEG4_WRITER_H_ 254