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