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