MPEG4Writer.h revision fe44e4f74fe2582cbf012687059278dbcbdaa6f7
19d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes/*
29d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * Copyright (C) 2009 The Android Open Source Project
39d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes *
49d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
59d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * you may not use this file except in compliance with the License.
69d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * You may obtain a copy of the License at
79d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes *
89d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
99d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes *
109d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * Unless required by applicable law or agreed to in writing, software
119d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
129d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * See the License for the specific language governing permissions and
149d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes * limitations under the License.
159d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes */
169d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
17fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#ifndef MPEG4_WRITER_H_
18fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom
199d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#define MPEG4_WRITER_H_
209d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
219d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include <stdio.h>
229d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
239d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include <media/IMediaSource.h>
249d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include <media/stagefright/MediaWriter.h>
259d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include <utils/List.h>
269d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include <utils/threads.h>
279d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include <media/stagefright/foundation/AHandlerReflector.h>
289d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes#include <media/stagefright/foundation/ALooper.h>
299d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
309d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesnamespace android {
319d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
329d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesclass AMessage;
339d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesclass MediaBuffer;
349d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesclass MetaData;
359d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
369d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesclass MPEG4Writer : public MediaWriter {
379d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughespublic:
389d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    MPEG4Writer(int fd);
399d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
409d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    // Limitations
419d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    // No more than one video and/or one audio source can be added, but
429d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    // multiple metadata sources can be added.
439d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    virtual status_t addSource(const sp<IMediaSource> &source);
449d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
459d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    // Returns INVALID_OPERATION if there is no source or track.
469d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    virtual status_t start(MetaData *param = NULL);
479d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    virtual status_t stop() { return reset(); }
489d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    virtual status_t pause();
499d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    virtual bool reachedEOS();
509d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    virtual status_t dump(int fd, const Vector<String16>& args);
519d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
529d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    void beginBox(const char *fourcc);
539d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    void beginBox(uint32_t id);
549d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    void writeInt8(int8_t x);
559d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    void writeInt16(int16_t x);
569d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    void writeInt32(int32_t x);
579d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    void writeInt64(int64_t x);
589d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    void writeCString(const char *s);
599d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    void writeFourcc(const char *fourcc);
609d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    void write(const void *data, size_t size);
619d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    inline size_t write(const void *ptr, size_t size, size_t nmemb);
62df1ce91ba97bc79a0637e5504b39318fb1c9f577Ian Rogers    void endBox();
639d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    uint32_t interleaveDuration() const { return mInterleaveDurationUs; }
649d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    status_t setInterleaveDuration(uint32_t duration);
659d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    int32_t getTimeScale() const { return mTimeScale; }
669d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
679d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    status_t setGeoData(int latitudex10000, int longitudex10000);
689d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    status_t setCaptureRate(float captureFps);
699d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    status_t setTemporalLayerCount(uint32_t layerCount);
709d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    void notifyApproachingLimit();
719d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    virtual void setStartTimeOffsetMs(int ms) { mStartTimeOffsetMs = ms; }
729d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    virtual int32_t getStartTimeOffsetMs() const { return mStartTimeOffsetMs; }
739d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    virtual status_t setNextFd(int fd);
749d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
759d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesprotected:
769d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    virtual ~MPEG4Writer();
779d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
789d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughesprivate:
799d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    class Track;
809d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    friend struct AHandlerReflector<MPEG4Writer>;
819d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
829d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    enum {
839d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes        kWhatSwitch                          = 'swch',
849d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    };
859d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes
869d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    int  mFd;
879d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    int mNextFd;
889d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    sp<MetaData> mStartMeta;
899d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    status_t mInitCheck;
909d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    bool mIsRealTimeRecording;
919d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    bool mUse4ByteNalLength;
929d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    bool mUse32BitOffset;
939d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    bool mIsFileSizeLimitExplicitlyRequested;
949d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    bool mPaused;
959d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    bool mStarted;  // Writer thread + track threads started successfully
969d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    bool mWriterThreadStarted;  // Only writer thread started successfully
979d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    bool mSendNotify;
989d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    off64_t mOffset;
999d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    off_t mMdatOffset;
1009d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    uint8_t *mMoovBoxBuffer;
1019d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    off64_t mMoovBoxBufferOffset;
1029d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    bool  mWriteMoovBoxToMemory;
1039d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    off64_t mFreeBoxOffset;
1049d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    bool mStreamableFile;
1059d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    off64_t mEstimatedMoovBoxSize;
1069d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    off64_t mMoovExtraSize;
1079d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    uint32_t mInterleaveDurationUs;
1089d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    int32_t mTimeScale;
1099d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    int64_t mStartTimestampUs;
1109d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    int mLatitudex10000;
1119d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    int mLongitudex10000;
1129d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    bool mAreGeoTagsAvailable;
1139d5ccec86d60c9ddd811836b9a2bc28d0b3d11feElliott Hughes    int32_t mStartTimeOffsetMs;
114fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom    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