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