MPEG4Writer.h revision fe44e4f74fe2582cbf012687059278dbcbdaa6f7
19d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes/* 29d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * Copyright (C) 2009 The Android Open Source Project 39d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * 49d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 59d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * you may not use this file except in compliance with the License. 69d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * You may obtain a copy of the License at 79d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * 89d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 99d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * 109d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * Unless required by applicable law or agreed to in writing, software 119d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 129d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * See the License for the specific language governing permissions and 149d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * limitations under the License. 159d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes */ 169d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 17fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#ifndef MPEG4_WRITER_H_ 18fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom 199d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#define MPEG4_WRITER_H_ 209d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 219d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include <stdio.h> 229d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 239d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include <media/IMediaSource.h> 249d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include <media/stagefright/MediaWriter.h> 259d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include <utils/List.h> 269d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include <utils/threads.h> 279d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include <media/stagefright/foundation/AHandlerReflector.h> 289d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include <media/stagefright/foundation/ALooper.h> 299d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 309d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesnamespace android { 319d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 329d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesclass AMessage; 339d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesclass MediaBuffer; 349d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesclass MetaData; 359d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 369d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesclass MPEG4Writer : public MediaWriter { 379d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughespublic: 389d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes MPEG4Writer(int fd); 399d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 409d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes // Limitations 419d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes // No more than one video and/or one audio source can be added, but 429d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes // multiple metadata sources can be added. 439d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes virtual status_t addSource(const sp<IMediaSource> &source); 449d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 459d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes // Returns INVALID_OPERATION if there is no source or track. 469d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes virtual status_t start(MetaData *param = NULL); 479d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes virtual status_t stop() { return reset(); } 489d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes virtual status_t pause(); 499d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes virtual bool reachedEOS(); 509d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes virtual status_t dump(int fd, const Vector<String16>& args); 519d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 529d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes void beginBox(const char *fourcc); 539d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes void beginBox(uint32_t id); 549d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes void writeInt8(int8_t x); 559d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes void writeInt16(int16_t x); 569d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes void writeInt32(int32_t x); 579d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes void writeInt64(int64_t x); 589d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes void writeCString(const char *s); 599d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes void writeFourcc(const char *fourcc); 609d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes void write(const void *data, size_t size); 619d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes inline size_t write(const void *ptr, size_t size, size_t nmemb); 62df1ce91ba97bc79a0637e5504b39318fb1c9f577Ian Rogers void endBox(); 639d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes uint32_t interleaveDuration() const { return mInterleaveDurationUs; } 649d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes status_t setInterleaveDuration(uint32_t duration); 659d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes int32_t getTimeScale() const { return mTimeScale; } 669d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 679d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes status_t setGeoData(int latitudex10000, int longitudex10000); 689d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes status_t setCaptureRate(float captureFps); 699d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes status_t setTemporalLayerCount(uint32_t layerCount); 709d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes void notifyApproachingLimit(); 719d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes virtual void setStartTimeOffsetMs(int ms) { mStartTimeOffsetMs = ms; } 729d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes virtual int32_t getStartTimeOffsetMs() const { return mStartTimeOffsetMs; } 739d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes virtual status_t setNextFd(int fd); 749d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 759d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesprotected: 769d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes virtual ~MPEG4Writer(); 779d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 789d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesprivate: 799d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes class Track; 809d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes friend struct AHandlerReflector<MPEG4Writer>; 819d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 829d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes enum { 839d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes kWhatSwitch = 'swch', 849d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes }; 859d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes 869d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes int mFd; 879d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes int mNextFd; 889d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes sp<MetaData> mStartMeta; 899d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes status_t mInitCheck; 909d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes bool mIsRealTimeRecording; 919d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes bool mUse4ByteNalLength; 929d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes bool mUse32BitOffset; 939d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes bool mIsFileSizeLimitExplicitlyRequested; 949d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes bool mPaused; 959d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes bool mStarted; // Writer thread + track threads started successfully 969d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes bool mWriterThreadStarted; // Only writer thread started successfully 979d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes bool mSendNotify; 989d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes off64_t mOffset; 999d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes off_t mMdatOffset; 1009d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes uint8_t *mMoovBoxBuffer; 1019d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes off64_t mMoovBoxBufferOffset; 1029d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes bool mWriteMoovBoxToMemory; 1039d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes off64_t mFreeBoxOffset; 1049d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes bool mStreamableFile; 1059d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes off64_t mEstimatedMoovBoxSize; 1069d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes off64_t mMoovExtraSize; 1079d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes uint32_t mInterleaveDurationUs; 1089d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes int32_t mTimeScale; 1099d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes int64_t mStartTimestampUs; 1109d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes int mLatitudex10000; 1119d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes int mLongitudex10000; 1129d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes bool mAreGeoTagsAvailable; 1139d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes int32_t mStartTimeOffsetMs; 114fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom 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