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/stagefright/MediaWriter.h> 24 #include <utils/List.h> 25 #include <utils/threads.h> 26 #include <media/stagefright/foundation/AHandlerReflector.h> 27 #include <media/stagefright/foundation/ALooper.h> 28 29 namespace android { 30 31 struct AMessage; 32 class MediaBuffer; 33 struct ABuffer; 34 35 class MPEG4Writer : public MediaWriter { 36 public: 37 MPEG4Writer(int fd); 38 39 // Limitations 40 // No more than one video and/or one audio source can be added, but 41 // multiple metadata sources can be added. 42 virtual status_t addSource(const sp<MediaSource> &source); 43 44 // Returns INVALID_OPERATION if there is no source or track. 45 virtual status_t start(MetaData *param = NULL); 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(); 62 uint32_t interleaveDuration() const { return mInterleaveDurationUs; } 63 status_t setInterleaveDuration(uint32_t duration); 64 int32_t getTimeScale() const { return mTimeScale; } 65 66 status_t setGeoData(int latitudex10000, int longitudex10000); 67 status_t setCaptureRate(float captureFps); 68 status_t setTemporalLayerCount(uint32_t layerCount); 69 void notifyApproachingLimit(); 70 virtual void setStartTimeOffsetMs(int ms) { mStartTimeOffsetMs = ms; } 71 virtual int32_t getStartTimeOffsetMs() const { return mStartTimeOffsetMs; } 72 virtual status_t setNextFd(int fd); 73 74 protected: 75 virtual ~MPEG4Writer(); 76 77 private: 78 class Track; 79 friend struct AHandlerReflector<MPEG4Writer>; 80 81 enum { 82 kWhatSwitch = 'swch', 83 }; 84 85 enum { 86 kMaxCttsOffsetTimeUs = 1000000LL, // 1 second 87 }; 88 89 int mFd; 90 int mNextFd; 91 sp<MetaData> mStartMeta; 92 status_t mInitCheck; 93 bool mIsRealTimeRecording; 94 bool mUse4ByteNalLength; 95 bool mUse32BitOffset; 96 bool mIsFileSizeLimitExplicitlyRequested; 97 bool mPaused; 98 bool mStarted; // Writer thread + track threads started successfully 99 bool mWriterThreadStarted; // Only writer thread started successfully 100 bool mSendNotify; 101 off64_t mOffset; 102 off_t mMdatOffset; 103 uint8_t *mInMemoryCache; 104 off64_t mInMemoryCacheOffset; 105 off64_t mInMemoryCacheSize; 106 bool mWriteBoxToMemory; 107 off64_t mFreeBoxOffset; 108 bool mStreamableFile; 109 off64_t mMoovExtraSize; 110 uint32_t mInterleaveDurationUs; 111 int32_t mTimeScale; 112 int64_t mStartTimestampUs; 113 int mLatitudex10000; 114 int mLongitudex10000; 115 bool mAreGeoTagsAvailable; 116 int32_t mStartTimeOffsetMs; 117 bool mSwitchPending; 118 119 sp<ALooper> mLooper; 120 sp<AHandlerReflector<MPEG4Writer> > mReflector; 121 122 Mutex mLock; 123 124 List<Track *> mTracks; 125 126 List<off64_t> mBoxes; 127 128 sp<AMessage> mMetaKeys; 129 130 void setStartTimestampUs(int64_t timeUs); 131 int64_t getStartTimestampUs(); // Not const 132 status_t startTracks(MetaData *params); 133 size_t numTracks(); 134 int64_t estimateMoovBoxSize(int32_t bitRate); 135 int64_t estimateFileLevelMetaSize(MetaData *params); 136 void writeCachedBoxToFile(const char *type); 137 138 struct Chunk { 139 Track *mTrack; // Owner 140 int64_t mTimeStampUs; // Timestamp of the 1st sample 141 List<MediaBuffer *> mSamples; // Sample data 142 143 // Convenient constructor 144 Chunk(): mTrack(NULL), mTimeStampUs(0) {} 145 146 Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples) 147 : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) { 148 } 149 150 }; 151 struct ChunkInfo { 152 Track *mTrack; // Owner 153 List<Chunk> mChunks; // Remaining chunks to be written 154 155 // Previous chunk timestamp that has been written 156 int64_t mPrevChunkTimestampUs; 157 158 // Max time interval between neighboring chunks 159 int64_t mMaxInterChunkDurUs; 160 161 }; 162 163 bool mIsFirstChunk; 164 volatile bool mDone; // Writer thread is done? 165 pthread_t mThread; // Thread id for the writer 166 List<ChunkInfo> mChunkInfos; // Chunk infos 167 Condition mChunkReadyCondition; // Signal that chunks are available 168 169 // HEIF writing 170 typedef key_value_pair_t< const char *, Vector<uint16_t> > ItemRefs; 171 typedef struct _ItemInfo { 172 bool isGrid() const { return !strcmp("grid", itemType); } 173 bool isImage() const { return !strcmp("hvc1", itemType) || isGrid(); } 174 const char *itemType; 175 uint16_t itemId; 176 bool isPrimary; 177 bool isHidden; 178 union { 179 // image item 180 struct { 181 uint32_t offset; 182 uint32_t size; 183 }; 184 // grid item 185 struct { 186 uint32_t rows; 187 uint32_t cols; 188 uint32_t width; 189 uint32_t height; 190 }; 191 }; 192 Vector<uint16_t> properties; 193 Vector<ItemRefs> refsList; 194 } ItemInfo; 195 196 typedef struct _ItemProperty { 197 uint32_t type; 198 int32_t width; 199 int32_t height; 200 int32_t rotation; 201 sp<ABuffer> hvcc; 202 } ItemProperty; 203 204 bool mHasFileLevelMeta; 205 bool mHasMoovBox; 206 uint32_t mPrimaryItemId; 207 uint32_t mAssociationEntryCount; 208 uint32_t mNumGrids; 209 bool mHasRefs; 210 Vector<ItemInfo> mItems; 211 Vector<ItemProperty> mProperties; 212 213 // Writer thread handling 214 status_t startWriterThread(); 215 void stopWriterThread(); 216 static void *ThreadWrapper(void *me); 217 void threadFunc(); 218 219 // Buffer a single chunk to be written out later. 220 void bufferChunk(const Chunk& chunk); 221 222 // Write all buffered chunks from all tracks 223 void writeAllChunks(); 224 225 // Retrieve the proper chunk to write if there is one 226 // Return true if a chunk is found; otherwise, return false. 227 bool findChunkToWrite(Chunk *chunk); 228 229 // Actually write the given chunk to the file. 230 void writeChunkToFile(Chunk* chunk); 231 232 // Adjust other track media clock (presumably wall clock) 233 // based on audio track media clock with the drift time. 234 int64_t mDriftTimeUs; 235 void setDriftTimeUs(int64_t driftTimeUs); 236 int64_t getDriftTimeUs(); 237 238 // Return whether the nal length is 4 bytes or 2 bytes 239 // Only makes sense for H.264/AVC 240 bool useNalLengthFour(); 241 242 // Return whether the writer is used for real time recording. 243 // In real time recording mode, new samples will be allowed to buffered into 244 // chunks in higher priority thread, even though the file writer has not 245 // drained the chunks yet. 246 // By default, real time recording is on. 247 bool isRealTimeRecording() const; 248 249 void lock(); 250 void unlock(); 251 252 // Init all the internal variables for each recording session. Some variables 253 // will only need to be set for the first recording session and they will stay 254 // the same across all the recording sessions. 255 void initInternal(int fd, bool isFirstSession); 256 257 // Acquire lock before calling these methods 258 off64_t addSample_l(MediaBuffer *buffer, bool usePrefix, bool isExif, size_t *bytesWritten); 259 void addLengthPrefixedSample_l(MediaBuffer *buffer); 260 void addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer); 261 uint16_t addProperty_l(const ItemProperty &); 262 uint16_t addItem_l(const ItemInfo &); 263 void addRefs_l(uint16_t itemId, const ItemRefs &); 264 265 bool exceedsFileSizeLimit(); 266 bool use32BitFileOffset() const; 267 bool exceedsFileDurationLimit(); 268 bool approachingFileSizeLimit(); 269 bool isFileStreamable() const; 270 void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK); 271 void writeCompositionMatrix(int32_t degrees); 272 void writeMvhdBox(int64_t durationUs); 273 void writeMoovBox(int64_t durationUs); 274 void writeFtypBox(MetaData *param); 275 void writeUdtaBox(); 276 void writeGeoDataBox(); 277 void writeLatitude(int degreex10000); 278 void writeLongitude(int degreex10000); 279 void finishCurrentSession(); 280 281 void addDeviceMeta(); 282 void writeHdlr(const char *handlerType); 283 void writeKeys(); 284 void writeIlst(); 285 void writeMoovLevelMetaBox(); 286 287 // HEIF writing 288 void writeIlocBox(); 289 void writeInfeBox(uint16_t itemId, const char *type, uint32_t flags); 290 void writeIinfBox(); 291 void writeIpcoBox(); 292 void writeIpmaBox(); 293 void writeIprpBox(); 294 void writeIdatBox(); 295 void writeIrefBox(); 296 void writePitmBox(); 297 void writeFileLevelMetaBox(); 298 299 void sendSessionSummary(); 300 void release(); 301 status_t switchFd(); 302 status_t reset(bool stopSource = true); 303 304 static uint32_t getMpeg4Time(); 305 306 void onMessageReceived(const sp<AMessage> &msg); 307 308 MPEG4Writer(const MPEG4Writer &); 309 MPEG4Writer &operator=(const MPEG4Writer &); 310 }; 311 312 } // namespace android 313 314 #endif // MPEG4_WRITER_H_ 315