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 32class 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 int mFd; 87 int mNextFd; 88 sp<MetaData> mStartMeta; 89 status_t mInitCheck; 90 bool mIsRealTimeRecording; 91 bool mUse4ByteNalLength; 92 bool mUse32BitOffset; 93 bool mIsFileSizeLimitExplicitlyRequested; 94 bool mPaused; 95 bool mStarted; // Writer thread + track threads started successfully 96 bool mWriterThreadStarted; // Only writer thread started successfully 97 bool mSendNotify; 98 off64_t mOffset; 99 off_t mMdatOffset; 100 uint8_t *mMoovBoxBuffer; 101 off64_t mMoovBoxBufferOffset; 102 bool mWriteMoovBoxToMemory; 103 off64_t mFreeBoxOffset; 104 bool mStreamableFile; 105 off64_t mEstimatedMoovBoxSize; 106 off64_t mMoovExtraSize; 107 uint32_t mInterleaveDurationUs; 108 int32_t mTimeScale; 109 int64_t mStartTimestampUs; 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 status_t startTracks(MetaData *params); 130 size_t numTracks(); 131 int64_t estimateMoovBoxSize(int32_t bitRate); 132 133 struct Chunk { 134 Track *mTrack; // Owner 135 int64_t mTimeStampUs; // Timestamp of the 1st sample 136 List<MediaBuffer *> mSamples; // Sample data 137 138 // Convenient constructor 139 Chunk(): mTrack(NULL), mTimeStampUs(0) {} 140 141 Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples) 142 : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) { 143 } 144 145 }; 146 struct ChunkInfo { 147 Track *mTrack; // Owner 148 List<Chunk> mChunks; // Remaining chunks to be written 149 150 // Previous chunk timestamp that has been written 151 int64_t mPrevChunkTimestampUs; 152 153 // Max time interval between neighboring chunks 154 int64_t mMaxInterChunkDurUs; 155 156 }; 157 158 bool mIsFirstChunk; 159 volatile bool mDone; // Writer thread is done? 160 pthread_t mThread; // Thread id for the writer 161 List<ChunkInfo> mChunkInfos; // Chunk infos 162 Condition mChunkReadyCondition; // Signal that chunks are available 163 164 // Writer thread handling 165 status_t startWriterThread(); 166 void stopWriterThread(); 167 static void *ThreadWrapper(void *me); 168 void threadFunc(); 169 170 // Buffer a single chunk to be written out later. 171 void bufferChunk(const Chunk& chunk); 172 173 // Write all buffered chunks from all tracks 174 void writeAllChunks(); 175 176 // Retrieve the proper chunk to write if there is one 177 // Return true if a chunk is found; otherwise, return false. 178 bool findChunkToWrite(Chunk *chunk); 179 180 // Actually write the given chunk to the file. 181 void writeChunkToFile(Chunk* chunk); 182 183 // Adjust other track media clock (presumably wall clock) 184 // based on audio track media clock with the drift time. 185 int64_t mDriftTimeUs; 186 void setDriftTimeUs(int64_t driftTimeUs); 187 int64_t getDriftTimeUs(); 188 189 // Return whether the nal length is 4 bytes or 2 bytes 190 // Only makes sense for H.264/AVC 191 bool useNalLengthFour(); 192 193 // Return whether the writer is used for real time recording. 194 // In real time recording mode, new samples will be allowed to buffered into 195 // chunks in higher priority thread, even though the file writer has not 196 // drained the chunks yet. 197 // By default, real time recording is on. 198 bool isRealTimeRecording() const; 199 200 void lock(); 201 void unlock(); 202 203 void initInternal(int fd); 204 205 // Acquire lock before calling these methods 206 off64_t addSample_l(MediaBuffer *buffer); 207 off64_t addLengthPrefixedSample_l(MediaBuffer *buffer); 208 off64_t addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer); 209 210 bool exceedsFileSizeLimit(); 211 bool use32BitFileOffset() const; 212 bool exceedsFileDurationLimit(); 213 bool approachingFileSizeLimit(); 214 bool isFileStreamable() const; 215 void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK); 216 void writeCompositionMatrix(int32_t degrees); 217 void writeMvhdBox(int64_t durationUs); 218 void writeMoovBox(int64_t durationUs); 219 void writeFtypBox(MetaData *param); 220 void writeUdtaBox(); 221 void writeGeoDataBox(); 222 void writeLatitude(int degreex10000); 223 void writeLongitude(int degreex10000); 224 void finishCurrentSession(); 225 226 void addDeviceMeta(); 227 void writeHdlr(); 228 void writeKeys(); 229 void writeIlst(); 230 void writeMetaBox(); 231 void sendSessionSummary(); 232 void release(); 233 status_t switchFd(); 234 status_t reset(bool stopSource = true); 235 236 static uint32_t getMpeg4Time(); 237 238 void onMessageReceived(const sp<AMessage> &msg); 239 240 MPEG4Writer(const MPEG4Writer &); 241 MPEG4Writer &operator=(const MPEG4Writer &); 242}; 243 244} // namespace android 245 246#endif // MPEG4_WRITER_H_ 247