blob: 0409b30746f51ad5aec124671dcbbe749a923e31 [file] [log] [blame]
Andreas Hubere46b7be2009-07-14 16:56:47 -07001/*
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
Andreas Huber996dddf2010-01-25 15:30:31 -080023#include <media/stagefright/MediaWriter.h>
Andreas Hubere46b7be2009-07-14 16:56:47 -070024#include <utils/List.h>
Andreas Hubere46b7be2009-07-14 16:56:47 -070025#include <utils/threads.h>
26
27namespace android {
28
29class MediaBuffer;
30class MediaSource;
31class MetaData;
32
Andreas Huber996dddf2010-01-25 15:30:31 -080033class MPEG4Writer : public MediaWriter {
Andreas Hubere46b7be2009-07-14 16:56:47 -070034public:
35 MPEG4Writer(const char *filename);
Andreas Huberea6a38c2009-11-16 15:43:38 -080036 MPEG4Writer(int fd);
Andreas Hubere46b7be2009-07-14 16:56:47 -070037
Andreas Huber996dddf2010-01-25 15:30:31 -080038 virtual status_t addSource(const sp<MediaSource> &source);
James Dong6feaa462010-06-20 08:20:54 -070039 virtual status_t start(MetaData *param = NULL);
James Dongc2240b12012-02-02 15:07:52 -080040 virtual status_t stop() { return reset(); }
James Dongd0366622010-08-18 19:10:39 -070041 virtual status_t pause();
Andreas Huber996dddf2010-01-25 15:30:31 -080042 virtual bool reachedEOS();
James Dong3f51fa72010-08-18 03:32:26 -070043 virtual status_t dump(int fd, const Vector<String16>& args);
Andreas Hubere46b7be2009-07-14 16:56:47 -070044
45 void beginBox(const char *fourcc);
46 void writeInt8(int8_t x);
47 void writeInt16(int16_t x);
48 void writeInt32(int32_t x);
49 void writeInt64(int64_t x);
50 void writeCString(const char *s);
51 void writeFourcc(const char *fourcc);
52 void write(const void *data, size_t size);
53 void endBox();
James Dong3300e962010-04-21 16:14:15 -070054 uint32_t interleaveDuration() const { return mInterleaveDurationUs; }
55 status_t setInterleaveDuration(uint32_t duration);
James Dong52d13f02010-07-02 11:39:06 -070056 int32_t getTimeScale() const { return mTimeScale; }
Andreas Hubere46b7be2009-07-14 16:56:47 -070057
James Dong987ab482011-05-11 19:09:25 -070058 status_t setGeoData(int latitudex10000, int longitudex10000);
James Dong13a33162011-05-09 16:56:25 -070059 void setStartTimeOffsetMs(int ms) { mStartTimeOffsetMs = ms; }
60 int32_t getStartTimeOffsetMs() const { return mStartTimeOffsetMs; }
James Dong987ab482011-05-11 19:09:25 -070061
Andreas Huberbe06d262009-08-14 14:37:10 -070062protected:
63 virtual ~MPEG4Writer();
64
Andreas Hubere46b7be2009-07-14 16:56:47 -070065private:
66 class Track;
67
James Dongb1262a82010-11-16 14:04:54 -080068 int mFd;
James Dong2747e0e2010-11-18 20:59:13 -080069 status_t mInitCheck;
James Dong7755cdd2010-09-02 10:49:55 -070070 bool mUse4ByteNalLength;
James Dong39a0b212010-06-23 00:18:40 -070071 bool mUse32BitOffset;
James Dong6a9e39a2010-10-04 16:41:53 -070072 bool mIsFileSizeLimitExplicitlyRequested;
James Dong08c74732010-06-10 12:28:15 -070073 bool mPaused;
James Dong0e27fce2011-07-08 16:51:16 -070074 bool mStarted; // Writer thread + track threads started successfully
75 bool mWriterThreadStarted; // Only writer thread started successfully
James Dongb1262a82010-11-16 14:04:54 -080076 off64_t mOffset;
Andreas Hubere46b7be2009-07-14 16:56:47 -070077 off_t mMdatOffset;
James Dongb5e74232010-05-07 10:26:24 -070078 uint8_t *mMoovBoxBuffer;
James Dongb1262a82010-11-16 14:04:54 -080079 off64_t mMoovBoxBufferOffset;
James Dongb5e74232010-05-07 10:26:24 -070080 bool mWriteMoovBoxToMemory;
James Dongb1262a82010-11-16 14:04:54 -080081 off64_t mFreeBoxOffset;
James Dongb5e74232010-05-07 10:26:24 -070082 bool mStreamableFile;
James Dongb1262a82010-11-16 14:04:54 -080083 off64_t mEstimatedMoovBoxSize;
James Dong3300e962010-04-21 16:14:15 -070084 uint32_t mInterleaveDurationUs;
James Dong52d13f02010-07-02 11:39:06 -070085 int32_t mTimeScale;
James Dong9db798d2010-05-13 11:47:36 -070086 int64_t mStartTimestampUs;
James Dong987ab482011-05-11 19:09:25 -070087 int mLatitudex10000;
88 int mLongitudex10000;
89 bool mAreGeoTagsAvailable;
James Dong13a33162011-05-09 16:56:25 -070090 int32_t mStartTimeOffsetMs;
James Dongda8073c2010-07-30 17:41:22 -070091
Andreas Hubere46b7be2009-07-14 16:56:47 -070092 Mutex mLock;
93
94 List<Track *> mTracks;
95
James Dongb1262a82010-11-16 14:04:54 -080096 List<off64_t> mBoxes;
Andreas Hubere46b7be2009-07-14 16:56:47 -070097
James Dong36e573b2010-06-19 09:04:18 -070098 void setStartTimestampUs(int64_t timeUs);
99 int64_t getStartTimestampUs(); // Not const
James Dong09936ed2010-06-24 19:04:27 -0700100 status_t startTracks(MetaData *params);
James Dongb54a91782010-06-22 11:27:37 -0700101 size_t numTracks();
James Dong6feaa462010-06-20 08:20:54 -0700102 int64_t estimateMoovBoxSize(int32_t bitRate);
James Dong9db798d2010-05-13 11:47:36 -0700103
James Dongda8073c2010-07-30 17:41:22 -0700104 struct Chunk {
105 Track *mTrack; // Owner
106 int64_t mTimeStampUs; // Timestamp of the 1st sample
107 List<MediaBuffer *> mSamples; // Sample data
108
109 // Convenient constructor
James Dongf6a2bff2011-02-09 14:00:55 -0800110 Chunk(): mTrack(NULL), mTimeStampUs(0) {}
111
James Dongda8073c2010-07-30 17:41:22 -0700112 Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples)
113 : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) {
114 }
115
116 };
117 struct ChunkInfo {
118 Track *mTrack; // Owner
119 List<Chunk> mChunks; // Remaining chunks to be written
James Dong3aea0372011-05-06 12:19:04 -0700120
121 // Previous chunk timestamp that has been written
122 int64_t mPrevChunkTimestampUs;
123
124 // Max time interval between neighboring chunks
125 int64_t mMaxInterChunkDurUs;
126
James Dongda8073c2010-07-30 17:41:22 -0700127 };
128
129 bool mIsFirstChunk;
130 volatile bool mDone; // Writer thread is done?
131 pthread_t mThread; // Thread id for the writer
132 List<ChunkInfo> mChunkInfos; // Chunk infos
133 Condition mChunkReadyCondition; // Signal that chunks are available
134
135 // Writer thread handling
136 status_t startWriterThread();
137 void stopWriterThread();
138 static void *ThreadWrapper(void *me);
139 void threadFunc();
140
141 // Buffer a single chunk to be written out later.
142 void bufferChunk(const Chunk& chunk);
143
144 // Write all buffered chunks from all tracks
James Dongf6a2bff2011-02-09 14:00:55 -0800145 void writeAllChunks();
James Dongda8073c2010-07-30 17:41:22 -0700146
James Dongf6a2bff2011-02-09 14:00:55 -0800147 // Retrieve the proper chunk to write if there is one
148 // Return true if a chunk is found; otherwise, return false.
149 bool findChunkToWrite(Chunk *chunk);
James Dongda8073c2010-07-30 17:41:22 -0700150
James Dongf6a2bff2011-02-09 14:00:55 -0800151 // Actually write the given chunk to the file.
152 void writeChunkToFile(Chunk* chunk);
James Dongda8073c2010-07-30 17:41:22 -0700153
James Dongb7208192010-08-02 19:13:40 -0700154 // Adjust other track media clock (presumably wall clock)
155 // based on audio track media clock with the drift time.
156 int64_t mDriftTimeUs;
James Dong4c238152010-09-01 18:48:35 -0700157 void setDriftTimeUs(int64_t driftTimeUs);
James Dongb7208192010-08-02 19:13:40 -0700158 int64_t getDriftTimeUs();
159
James Dong7755cdd2010-09-02 10:49:55 -0700160 // Return whether the nal length is 4 bytes or 2 bytes
161 // Only makes sense for H.264/AVC
162 bool useNalLengthFour();
163
James Dong3300e962010-04-21 16:14:15 -0700164 void lock();
165 void unlock();
166
167 // Acquire lock before calling these methods
James Dongb1262a82010-11-16 14:04:54 -0800168 off64_t addSample_l(MediaBuffer *buffer);
169 off64_t addLengthPrefixedSample_l(MediaBuffer *buffer);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700170
James Dong2747e0e2010-11-18 20:59:13 -0800171 inline size_t write(const void *ptr, size_t size, size_t nmemb);
James Dong18244862010-05-11 14:57:02 -0700172 bool exceedsFileSizeLimit();
James Dongcb7e65c2010-09-02 11:19:11 -0700173 bool use32BitFileOffset() const;
James Dong18244862010-05-11 14:57:02 -0700174 bool exceedsFileDurationLimit();
James Dong22b37fa2010-10-19 21:28:47 -0700175 bool isFileStreamable() const;
James Dong7fc8b4f2011-03-18 11:25:41 -0700176 void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK);
James Dongb9d7e012010-11-09 11:15:47 -0800177 void writeCompositionMatrix(int32_t degrees);
James Dong7a6cea42011-05-06 16:55:39 -0700178 void writeMvhdBox(int64_t durationUs);
179 void writeMoovBox(int64_t durationUs);
James Dongf84e4a62011-05-17 22:39:06 -0700180 void writeFtypBox(MetaData *param);
James Dong987ab482011-05-11 19:09:25 -0700181 void writeUdtaBox();
182 void writeGeoDataBox();
183 void writeLatitude(int degreex10000);
184 void writeLongitude(int degreex10000);
James Dong3aea0372011-05-06 12:19:04 -0700185 void sendSessionSummary();
James Dong0e27fce2011-07-08 16:51:16 -0700186 void release();
James Dongc2240b12012-02-02 15:07:52 -0800187 status_t reset();
James Dongb5e74232010-05-07 10:26:24 -0700188
Andreas Hubere46b7be2009-07-14 16:56:47 -0700189 MPEG4Writer(const MPEG4Writer &);
190 MPEG4Writer &operator=(const MPEG4Writer &);
191};
192
193} // namespace android
194
195#endif // MPEG4_WRITER_H_