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 
28 namespace android {
29 
30 class AMessage;
31 class MediaBuffer;
32 class MetaData;
33 
34 class MPEG4Writer : public MediaWriter {
35 public:
36     MPEG4Writer(int fd);
37 
38     // Limitations
39     // 1. No more than 2 tracks can be added
40     // 2. Only video or audio source can be added
41     // 3. No more than one video and/or one audio source can be added.
42     virtual status_t addSource(const sp<IMediaSource> &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);
setStartTimeOffsetMs(int ms)68     virtual void setStartTimeOffsetMs(int ms) { mStartTimeOffsetMs = ms; }
getStartTimeOffsetMs()69     virtual int32_t getStartTimeOffsetMs() const { return mStartTimeOffsetMs; }
70 
71 protected:
72     virtual ~MPEG4Writer();
73 
74 private:
75     class Track;
76 
77     int  mFd;
78     status_t mInitCheck;
79     bool mIsRealTimeRecording;
80     bool mUse4ByteNalLength;
81     bool mUse32BitOffset;
82     bool mIsFileSizeLimitExplicitlyRequested;
83     bool mPaused;
84     bool mStarted;  // Writer thread + track threads started successfully
85     bool mWriterThreadStarted;  // Only writer thread started successfully
86     off64_t mOffset;
87     off_t mMdatOffset;
88     uint8_t *mMoovBoxBuffer;
89     off64_t mMoovBoxBufferOffset;
90     bool  mWriteMoovBoxToMemory;
91     off64_t mFreeBoxOffset;
92     bool mStreamableFile;
93     off64_t mEstimatedMoovBoxSize;
94     off64_t mMoovExtraSize;
95     uint32_t mInterleaveDurationUs;
96     int32_t mTimeScale;
97     int64_t mStartTimestampUs;
98     int mLatitudex10000;
99     int mLongitudex10000;
100     bool mAreGeoTagsAvailable;
101     int32_t mStartTimeOffsetMs;
102 
103     Mutex mLock;
104 
105     List<Track *> mTracks;
106 
107     List<off64_t> mBoxes;
108 
109     sp<AMessage> mMetaKeys;
110 
111     void setStartTimestampUs(int64_t timeUs);
112     int64_t getStartTimestampUs();  // Not const
113     status_t startTracks(MetaData *params);
114     size_t numTracks();
115     int64_t estimateMoovBoxSize(int32_t bitRate);
116 
117     struct Chunk {
118         Track               *mTrack;        // Owner
119         int64_t             mTimeStampUs;   // Timestamp of the 1st sample
120         List<MediaBuffer *> mSamples;       // Sample data
121 
122         // Convenient constructor
ChunkChunk123         Chunk(): mTrack(NULL), mTimeStampUs(0) {}
124 
ChunkChunk125         Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples)
126             : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) {
127         }
128 
129     };
130     struct ChunkInfo {
131         Track               *mTrack;        // Owner
132         List<Chunk>         mChunks;        // Remaining chunks to be written
133 
134         // Previous chunk timestamp that has been written
135         int64_t mPrevChunkTimestampUs;
136 
137         // Max time interval between neighboring chunks
138         int64_t mMaxInterChunkDurUs;
139 
140     };
141 
142     bool            mIsFirstChunk;
143     volatile bool   mDone;                  // Writer thread is done?
144     pthread_t       mThread;                // Thread id for the writer
145     List<ChunkInfo> mChunkInfos;            // Chunk infos
146     Condition       mChunkReadyCondition;   // Signal that chunks are available
147 
148     // Writer thread handling
149     status_t startWriterThread();
150     void stopWriterThread();
151     static void *ThreadWrapper(void *me);
152     void threadFunc();
153 
154     // Buffer a single chunk to be written out later.
155     void bufferChunk(const Chunk& chunk);
156 
157     // Write all buffered chunks from all tracks
158     void writeAllChunks();
159 
160     // Retrieve the proper chunk to write if there is one
161     // Return true if a chunk is found; otherwise, return false.
162     bool findChunkToWrite(Chunk *chunk);
163 
164     // Actually write the given chunk to the file.
165     void writeChunkToFile(Chunk* chunk);
166 
167     // Adjust other track media clock (presumably wall clock)
168     // based on audio track media clock with the drift time.
169     int64_t mDriftTimeUs;
170     void setDriftTimeUs(int64_t driftTimeUs);
171     int64_t getDriftTimeUs();
172 
173     // Return whether the nal length is 4 bytes or 2 bytes
174     // Only makes sense for H.264/AVC
175     bool useNalLengthFour();
176 
177     // Return whether the writer is used for real time recording.
178     // In real time recording mode, new samples will be allowed to buffered into
179     // chunks in higher priority thread, even though the file writer has not
180     // drained the chunks yet.
181     // By default, real time recording is on.
182     bool isRealTimeRecording() const;
183 
184     void lock();
185     void unlock();
186 
187     // Acquire lock before calling these methods
188     off64_t addSample_l(MediaBuffer *buffer);
189     off64_t addLengthPrefixedSample_l(MediaBuffer *buffer);
190 
191     bool exceedsFileSizeLimit();
192     bool use32BitFileOffset() const;
193     bool exceedsFileDurationLimit();
194     bool isFileStreamable() const;
195     void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK);
196     void writeCompositionMatrix(int32_t degrees);
197     void writeMvhdBox(int64_t durationUs);
198     void writeMoovBox(int64_t durationUs);
199     void writeFtypBox(MetaData *param);
200     void writeUdtaBox();
201     void writeGeoDataBox();
202     void writeLatitude(int degreex10000);
203     void writeLongitude(int degreex10000);
204 
205     void addDeviceMeta();
206     void writeHdlr();
207     void writeKeys();
208     void writeIlst();
209     void writeMetaBox();
210     void sendSessionSummary();
211     void release();
212     status_t reset();
213 
214     static uint32_t getMpeg4Time();
215 
216     MPEG4Writer(const MPEG4Writer &);
217     MPEG4Writer &operator=(const MPEG4Writer &);
218 };
219 
220 }  // namespace android
221 
222 #endif  // MPEG4_WRITER_H_
223