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); 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); 68 status_t setTemporalLayerCount(uint32_t layerCount); 69 void notifyApproachingLimit(); setStartTimeOffsetMs(int ms)70 virtual void setStartTimeOffsetMs(int ms) { mStartTimeOffsetMs = ms; } getStartTimeOffsetMs()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 int mFd; 86 int mNextFd; 87 sp<MetaData> mStartMeta; 88 status_t mInitCheck; 89 bool mIsRealTimeRecording; 90 bool mUse4ByteNalLength; 91 bool mUse32BitOffset; 92 bool mIsFileSizeLimitExplicitlyRequested; 93 bool mPaused; 94 bool mStarted; // Writer thread + track threads started successfully 95 bool mWriterThreadStarted; // Only writer thread started successfully 96 bool mSendNotify; 97 off64_t mOffset; 98 off_t mMdatOffset; 99 uint8_t *mInMemoryCache; 100 off64_t mInMemoryCacheOffset; 101 off64_t mInMemoryCacheSize; 102 bool mWriteBoxToMemory; 103 off64_t mFreeBoxOffset; 104 bool mStreamableFile; 105 off64_t mMoovExtraSize; 106 uint32_t mInterleaveDurationUs; 107 int32_t mTimeScale; 108 int64_t mStartTimestampUs; 109 int32_t mStartTimeOffsetBFramesUs; // Start time offset when B Frames are present 110 int mLatitudex10000; 111 int mLongitudex10000; 112 bool mAreGeoTagsAvailable; 113 int32_t mStartTimeOffsetMs; 114 bool mSwitchPending; 115 116 sp<ALooper> mLooper; 117 sp<AHandlerReflector<MPEG4Writer> > mReflector; 118 119 Mutex mLock; 120 121 List<Track *> mTracks; 122 123 List<off64_t> mBoxes; 124 125 sp<AMessage> mMetaKeys; 126 127 void setStartTimestampUs(int64_t timeUs); 128 int64_t getStartTimestampUs(); // Not const 129 int32_t getStartTimeOffsetBFramesUs(); 130 status_t startTracks(MetaData *params); 131 size_t numTracks(); 132 int64_t estimateMoovBoxSize(int32_t bitRate); 133 int64_t estimateFileLevelMetaSize(MetaData *params); 134 void writeCachedBoxToFile(const char *type); 135 136 struct Chunk { 137 Track *mTrack; // Owner 138 int64_t mTimeStampUs; // Timestamp of the 1st sample 139 List<MediaBuffer *> mSamples; // Sample data 140 141 // Convenient constructor 142 Chunk(): mTrack(NULL), mTimeStampUs(0) {} 143 144 Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples) 145 : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) { 146 } 147 148 }; 149 struct ChunkInfo { 150 Track *mTrack; // Owner 151 List<Chunk> mChunks; // Remaining chunks to be written 152 153 // Previous chunk timestamp that has been written 154 int64_t mPrevChunkTimestampUs; 155 156 // Max time interval between neighboring chunks 157 int64_t mMaxInterChunkDurUs; 158 159 }; 160 161 bool mIsFirstChunk; 162 volatile bool mDone; // Writer thread is done? 163 pthread_t mThread; // Thread id for the writer 164 List<ChunkInfo> mChunkInfos; // Chunk infos 165 Condition mChunkReadyCondition; // Signal that chunks are available 166 167 // HEIF writing 168 typedef key_value_pair_t< const char *, Vector<uint16_t> > ItemRefs; 169 typedef struct _ItemInfo { 170 bool isGrid() const { return !strcmp("grid", itemType); } 171 bool isImage() const { return !strcmp("hvc1", itemType) || isGrid(); } 172 const char *itemType; 173 uint16_t itemId; 174 bool isPrimary; 175 bool isHidden; 176 union { 177 // image item 178 struct { 179 uint32_t offset; 180 uint32_t size; 181 }; 182 // grid item 183 struct { 184 uint32_t rows; 185 uint32_t cols; 186 uint32_t width; 187 uint32_t height; 188 }; 189 }; 190 Vector<uint16_t> properties; 191 Vector<ItemRefs> refsList; 192 } ItemInfo; 193 194 typedef struct _ItemProperty { 195 uint32_t type; 196 int32_t width; 197 int32_t height; 198 int32_t rotation; 199 sp<ABuffer> hvcc; 200 } ItemProperty; 201 202 bool mHasFileLevelMeta; 203 bool mHasMoovBox; 204 uint32_t mPrimaryItemId; 205 uint32_t mAssociationEntryCount; 206 uint32_t mNumGrids; 207 bool mHasRefs; 208 Vector<ItemInfo> mItems; 209 Vector<ItemProperty> mProperties; 210 211 // Writer thread handling 212 status_t startWriterThread(); 213 void stopWriterThread(); 214 static void *ThreadWrapper(void *me); 215 void threadFunc(); 216 217 // Buffer a single chunk to be written out later. 218 void bufferChunk(const Chunk& chunk); 219 220 // Write all buffered chunks from all tracks 221 void writeAllChunks(); 222 223 // Retrieve the proper chunk to write if there is one 224 // Return true if a chunk is found; otherwise, return false. 225 bool findChunkToWrite(Chunk *chunk); 226 227 // Actually write the given chunk to the file. 228 void writeChunkToFile(Chunk* chunk); 229 230 // Adjust other track media clock (presumably wall clock) 231 // based on audio track media clock with the drift time. 232 int64_t mDriftTimeUs; 233 void setDriftTimeUs(int64_t driftTimeUs); 234 int64_t getDriftTimeUs(); 235 236 // Return whether the nal length is 4 bytes or 2 bytes 237 // Only makes sense for H.264/AVC 238 bool useNalLengthFour(); 239 240 // Return whether the writer is used for real time recording. 241 // In real time recording mode, new samples will be allowed to buffered into 242 // chunks in higher priority thread, even though the file writer has not 243 // drained the chunks yet. 244 // By default, real time recording is on. 245 bool isRealTimeRecording() const; 246 247 void lock(); 248 void unlock(); 249 250 // Init all the internal variables for each recording session. Some variables 251 // will only need to be set for the first recording session and they will stay 252 // the same across all the recording sessions. 253 void initInternal(int fd, bool isFirstSession); 254 255 // Acquire lock before calling these methods 256 off64_t addSample_l( 257 MediaBuffer *buffer, bool usePrefix, 258 uint32_t tiffHdrOffset, 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