MPEG4Writer.h revision 07b1bb529a1ae76c46a71b01338c166f9490629d
14be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi/*
24be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi * Copyright (C) 2009 The Android Open Source Project
34be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi *
44be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
54be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi * you may not use this file except in compliance with the License.
64be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi * You may obtain a copy of the License at
74be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi *
84be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
94be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi *
104be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
114be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
124be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi * See the License for the specific language governing permissions and
144be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi * limitations under the License.
154be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi */
164be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
174be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#ifndef MPEG4_WRITER_H_
184be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
194be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#define MPEG4_WRITER_H_
204be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
214be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#include <stdio.h>
224be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
234be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#include <media/stagefright/MediaWriter.h>
244be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#include <utils/List.h>
254be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#include <utils/threads.h>
264be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
274be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivinamespace android {
284be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
294be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Triviclass MediaBuffer;
304be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Triviclass MediaSource;
314be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Triviclass MetaData;
324be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
334be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Triviclass MPEG4Writer : public MediaWriter {
344be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivipublic:
354be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    MPEG4Writer(const char *filename);
364be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    MPEG4Writer(int fd);
374be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
384be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    virtual status_t addSource(const sp<MediaSource> &source);
394be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    virtual status_t start(MetaData *param = NULL);
404be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    virtual status_t stop();
414be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    virtual status_t pause();
424be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    virtual bool reachedEOS();
434be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    virtual status_t dump(int fd, const Vector<String16>& args);
444be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
454be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void beginBox(const char *fourcc);
464be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void writeInt8(int8_t x);
474be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void writeInt16(int16_t x);
484be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void writeInt32(int32_t x);
494be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void writeInt64(int64_t x);
504be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void writeCString(const char *s);
514be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void writeFourcc(const char *fourcc);
524be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void write(const void *data, size_t size);
534be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void endBox();
544be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    uint32_t interleaveDuration() const { return mInterleaveDurationUs; }
554be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    status_t setInterleaveDuration(uint32_t duration);
564be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    int32_t getTimeScale() const { return mTimeScale; }
574be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
584be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    status_t setGeoData(int latitudex10000, int longitudex10000);
594be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
604be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Triviprotected:
614be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    virtual ~MPEG4Writer();
624be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
634be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Triviprivate:
64b3b757daa7d162b6f66590d917c1f84f3ba73c70Eric Laurent    class Track;
65b3b757daa7d162b6f66590d917c1f84f3ba73c70Eric Laurent
66b3b757daa7d162b6f66590d917c1f84f3ba73c70Eric Laurent    int  mFd;
67b3b757daa7d162b6f66590d917c1f84f3ba73c70Eric Laurent    status_t mInitCheck;
68b3b757daa7d162b6f66590d917c1f84f3ba73c70Eric Laurent    bool mUse4ByteNalLength;
694be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    bool mUse32BitOffset;
704be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    bool mIsFileSizeLimitExplicitlyRequested;
714be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    bool mPaused;
724be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    bool mStarted;
734be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    off64_t mOffset;
744be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    off_t mMdatOffset;
754be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    uint8_t *mMoovBoxBuffer;
764be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    off64_t mMoovBoxBufferOffset;
774be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    bool  mWriteMoovBoxToMemory;
784be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    off64_t mFreeBoxOffset;
794be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    bool mStreamableFile;
804be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    off64_t mEstimatedMoovBoxSize;
814be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    uint32_t mInterleaveDurationUs;
824be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    int32_t mTimeScale;
834be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    int64_t mStartTimestampUs;
844be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    int mLatitudex10000;
854be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    int mLongitudex10000;
864be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    bool mAreGeoTagsAvailable;
874be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
884be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    Mutex mLock;
894be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
904be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    List<Track *> mTracks;
914be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
924be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    List<off64_t> mBoxes;
934be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
944be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void setStartTimestampUs(int64_t timeUs);
954be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    int64_t getStartTimestampUs();  // Not const
964be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    status_t startTracks(MetaData *params);
974be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    size_t numTracks();
984be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    int64_t estimateMoovBoxSize(int32_t bitRate);
994be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1004be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    struct Chunk {
1014be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi        Track               *mTrack;        // Owner
1024be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi        int64_t             mTimeStampUs;   // Timestamp of the 1st sample
1034be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi        List<MediaBuffer *> mSamples;       // Sample data
1044be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1054be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi        // Convenient constructor
1064be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi        Chunk(): mTrack(NULL), mTimeStampUs(0) {}
1074be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1084be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi        Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples)
1094be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi            : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) {
1104be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi        }
1114be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1124be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    };
1134be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    struct ChunkInfo {
1144be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi        Track               *mTrack;        // Owner
1154be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi        List<Chunk>         mChunks;        // Remaining chunks to be written
1164be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1174be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi        // Previous chunk timestamp that has been written
1184be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi        int64_t mPrevChunkTimestampUs;
1194be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1204be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi        // Max time interval between neighboring chunks
1214be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi        int64_t mMaxInterChunkDurUs;
1224be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1234be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    };
1244be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1254be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    bool            mIsFirstChunk;
1264be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    volatile bool   mDone;                  // Writer thread is done?
1274be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    pthread_t       mThread;                // Thread id for the writer
1284be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    List<ChunkInfo> mChunkInfos;            // Chunk infos
1294be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    Condition       mChunkReadyCondition;   // Signal that chunks are available
1304be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1314be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    // Writer thread handling
1324be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    status_t startWriterThread();
1334be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void stopWriterThread();
1344be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    static void *ThreadWrapper(void *me);
1354be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void threadFunc();
1364be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1374be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    // Buffer a single chunk to be written out later.
1384be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void bufferChunk(const Chunk& chunk);
1394be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1404be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    // Write all buffered chunks from all tracks
1414be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void writeAllChunks();
1424be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1434be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    // Retrieve the proper chunk to write if there is one
1444be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    // Return true if a chunk is found; otherwise, return false.
1454be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    bool findChunkToWrite(Chunk *chunk);
1464be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1474be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    // Actually write the given chunk to the file.
1484be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void writeChunkToFile(Chunk* chunk);
1494be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1504be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    // Adjust other track media clock (presumably wall clock)
1514be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    // based on audio track media clock with the drift time.
1524be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    int64_t mDriftTimeUs;
1534be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void setDriftTimeUs(int64_t driftTimeUs);
1544be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    int64_t getDriftTimeUs();
1554be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
156b3b757daa7d162b6f66590d917c1f84f3ba73c70Eric Laurent    // Return whether the nal length is 4 bytes or 2 bytes
1574be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    // Only makes sense for H.264/AVC
1584be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    bool useNalLengthFour();
1594be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1604be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void lock();
161b3b757daa7d162b6f66590d917c1f84f3ba73c70Eric Laurent    void unlock();
1624be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1634be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    // Acquire lock before calling these methods
1644be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    off64_t addSample_l(MediaBuffer *buffer);
1654be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    off64_t addLengthPrefixedSample_l(MediaBuffer *buffer);
1664be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1674be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    inline size_t write(const void *ptr, size_t size, size_t nmemb);
1684be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    bool exceedsFileSizeLimit();
1694be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    bool use32BitFileOffset() const;
1704be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    bool exceedsFileDurationLimit();
171b3b757daa7d162b6f66590d917c1f84f3ba73c70Eric Laurent    bool isFileStreamable() const;
1724be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK);
1734be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void writeCompositionMatrix(int32_t degrees);
1744be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void writeMvhdBox(int64_t durationUs);
1754be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void writeMoovBox(int64_t durationUs);
1764be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void writeFtypBox(const MetaData *param);
1774be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void writeUdtaBox();
1784be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void writeGeoDataBox();
1794be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void writeLatitude(int degreex10000);
1804be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void writeLongitude(int degreex10000);
1814be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    void sendSessionSummary();
1824be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1834be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    MPEG4Writer(const MPEG4Writer &);
1844be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi    MPEG4Writer &operator=(const MPEG4Writer &);
1854be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi};
1864be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1874be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi}  // namespace android
1884be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi
1894be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi#endif  // MPEG4_WRITER_H_
1904be7fe875758b42939719a1082ae9e6dbf37a1d7Jean-Michel Trivi