1e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber/*
2e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Copyright (C) 2009 The Android Open Source Project
3e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *
4e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * you may not use this file except in compliance with the License.
6e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * You may obtain a copy of the License at
7e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *
8e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *
10e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Unless required by applicable law or agreed to in writing, software
11e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * See the License for the specific language governing permissions and
14e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * limitations under the License.
15e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber */
16e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
17e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#ifndef MPEG4_WRITER_H_
18e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
19e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#define MPEG4_WRITER_H_
20e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
21e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <stdio.h>
22e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
23996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber#include <media/stagefright/MediaWriter.h>
24e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <utils/List.h>
25e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <utils/threads.h>
26e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
27e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubernamespace android {
28e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
29e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberclass MediaBuffer;
30e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberclass MediaSource;
31e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberclass MetaData;
32e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
33996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huberclass MPEG4Writer : public MediaWriter {
34e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberpublic:
35e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MPEG4Writer(const char *filename);
36ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber    MPEG4Writer(int fd);
37e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
38996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    virtual status_t addSource(const sp<MediaSource> &source);
396feaa46496bae85adbe10e84611592612f898081James Dong    virtual status_t start(MetaData *param = NULL);
40d036662470ceb6b20b0591b7d4123f2db911536dJames Dong    virtual status_t stop();
41d036662470ceb6b20b0591b7d4123f2db911536dJames Dong    virtual status_t pause();
42996dddff64f90d8469e24107c44bfd618cf0c2ddAndreas Huber    virtual bool reachedEOS();
433f51fa78ada0e064d23db5961337280c267cc2c0James Dong    virtual status_t dump(int fd, const Vector<String16>& args);
44e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
45e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    void beginBox(const char *fourcc);
46e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    void writeInt8(int8_t x);
47e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    void writeInt16(int16_t x);
48e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    void writeInt32(int32_t x);
49e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    void writeInt64(int64_t x);
50e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    void writeCString(const char *s);
51e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    void writeFourcc(const char *fourcc);
52e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    void write(const void *data, size_t size);
53e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    void endBox();
543300e9667e3daa374659b4a8b97dd92c4d34e501James Dong    uint32_t interleaveDuration() const { return mInterleaveDurationUs; }
553300e9667e3daa374659b4a8b97dd92c4d34e501James Dong    status_t setInterleaveDuration(uint32_t duration);
5652d13f01a60f04d5a8a181ceb5400e32aee5637dJames Dong    int32_t getTimeScale() const { return mTimeScale; }
57e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
58be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huberprotected:
59be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber    virtual ~MPEG4Writer();
60be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber
61e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberprivate:
62e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    class Track;
63e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
64e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    FILE *mFile;
657755cdd69690ccbb42c6fd47b3e9c4594d4ade82James Dong    bool mUse4ByteNalLength;
6639a0b21c65c3bbadc9a3c6b5346b45fac842d0f7James Dong    bool mUse32BitOffset;
676a9e39ac55b32a2847546ef1784c2d6c91863a55James Dong    bool mIsFileSizeLimitExplicitlyRequested;
6808c7473ce9b601e170fd79c530f106bf74277a0fJames Dong    bool mPaused;
6908c7473ce9b601e170fd79c530f106bf74277a0fJames Dong    bool mStarted;
70e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    off_t mOffset;
71e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    off_t mMdatOffset;
72b5e742397d4129e191d65d51da55302b504f3c99James Dong    uint8_t *mMoovBoxBuffer;
73b5e742397d4129e191d65d51da55302b504f3c99James Dong    off_t mMoovBoxBufferOffset;
74b5e742397d4129e191d65d51da55302b504f3c99James Dong    bool  mWriteMoovBoxToMemory;
75b5e742397d4129e191d65d51da55302b504f3c99James Dong    off_t mFreeBoxOffset;
76b5e742397d4129e191d65d51da55302b504f3c99James Dong    bool mStreamableFile;
77b5e742397d4129e191d65d51da55302b504f3c99James Dong    off_t mEstimatedMoovBoxSize;
783300e9667e3daa374659b4a8b97dd92c4d34e501James Dong    uint32_t mInterleaveDurationUs;
7952d13f01a60f04d5a8a181ceb5400e32aee5637dJames Dong    int32_t mTimeScale;
809db798d0f07213071a65237e9ece758c9e8c7b99James Dong    int64_t mStartTimestampUs;
81da8073c68e63179e1d4f5fb562e5625af686c984James Dong
82e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    Mutex mLock;
83e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
84e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    List<Track *> mTracks;
85e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
86e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    List<off_t> mBoxes;
87e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
8836e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    void setStartTimestampUs(int64_t timeUs);
8936e573bf7db5888f92c52eda26e0771aaa2406e4James Dong    int64_t getStartTimestampUs();  // Not const
9009936ed19263854e937198af03d9805a8b669ca1James Dong    status_t startTracks(MetaData *params);
91b54a91784291bf14b1f486f7d4349774073593c5James Dong    size_t numTracks();
926feaa46496bae85adbe10e84611592612f898081James Dong    int64_t estimateMoovBoxSize(int32_t bitRate);
939db798d0f07213071a65237e9ece758c9e8c7b99James Dong
94da8073c68e63179e1d4f5fb562e5625af686c984James Dong    struct Chunk {
95da8073c68e63179e1d4f5fb562e5625af686c984James Dong        Track               *mTrack;        // Owner
96da8073c68e63179e1d4f5fb562e5625af686c984James Dong        int64_t             mTimeStampUs;   // Timestamp of the 1st sample
97da8073c68e63179e1d4f5fb562e5625af686c984James Dong        List<MediaBuffer *> mSamples;       // Sample data
98da8073c68e63179e1d4f5fb562e5625af686c984James Dong
99da8073c68e63179e1d4f5fb562e5625af686c984James Dong        // Convenient constructor
100da8073c68e63179e1d4f5fb562e5625af686c984James Dong        Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples)
101da8073c68e63179e1d4f5fb562e5625af686c984James Dong            : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) {
102da8073c68e63179e1d4f5fb562e5625af686c984James Dong        }
103da8073c68e63179e1d4f5fb562e5625af686c984James Dong
104da8073c68e63179e1d4f5fb562e5625af686c984James Dong    };
105da8073c68e63179e1d4f5fb562e5625af686c984James Dong    struct ChunkInfo {
106da8073c68e63179e1d4f5fb562e5625af686c984James Dong        Track               *mTrack;        // Owner
107da8073c68e63179e1d4f5fb562e5625af686c984James Dong        List<Chunk>         mChunks;        // Remaining chunks to be written
108da8073c68e63179e1d4f5fb562e5625af686c984James Dong    };
109da8073c68e63179e1d4f5fb562e5625af686c984James Dong
110da8073c68e63179e1d4f5fb562e5625af686c984James Dong    bool            mIsFirstChunk;
111da8073c68e63179e1d4f5fb562e5625af686c984James Dong    volatile bool   mDone;                  // Writer thread is done?
112da8073c68e63179e1d4f5fb562e5625af686c984James Dong    pthread_t       mThread;                // Thread id for the writer
113da8073c68e63179e1d4f5fb562e5625af686c984James Dong    List<ChunkInfo> mChunkInfos;            // Chunk infos
114da8073c68e63179e1d4f5fb562e5625af686c984James Dong    Condition       mChunkReadyCondition;   // Signal that chunks are available
115da8073c68e63179e1d4f5fb562e5625af686c984James Dong
116da8073c68e63179e1d4f5fb562e5625af686c984James Dong    // Writer thread handling
117da8073c68e63179e1d4f5fb562e5625af686c984James Dong    status_t startWriterThread();
118da8073c68e63179e1d4f5fb562e5625af686c984James Dong    void stopWriterThread();
119da8073c68e63179e1d4f5fb562e5625af686c984James Dong    static void *ThreadWrapper(void *me);
120da8073c68e63179e1d4f5fb562e5625af686c984James Dong    void threadFunc();
121da8073c68e63179e1d4f5fb562e5625af686c984James Dong
122da8073c68e63179e1d4f5fb562e5625af686c984James Dong    // Buffer a single chunk to be written out later.
123da8073c68e63179e1d4f5fb562e5625af686c984James Dong    void bufferChunk(const Chunk& chunk);
124da8073c68e63179e1d4f5fb562e5625af686c984James Dong
125da8073c68e63179e1d4f5fb562e5625af686c984James Dong    // Write all buffered chunks from all tracks
126da8073c68e63179e1d4f5fb562e5625af686c984James Dong    void writeChunks();
127da8073c68e63179e1d4f5fb562e5625af686c984James Dong
128da8073c68e63179e1d4f5fb562e5625af686c984James Dong    // Write a chunk if there is one
129da8073c68e63179e1d4f5fb562e5625af686c984James Dong    status_t writeOneChunk();
130da8073c68e63179e1d4f5fb562e5625af686c984James Dong
131da8073c68e63179e1d4f5fb562e5625af686c984James Dong    // Write the first chunk from the given ChunkInfo.
132da8073c68e63179e1d4f5fb562e5625af686c984James Dong    void writeFirstChunk(ChunkInfo* info);
133da8073c68e63179e1d4f5fb562e5625af686c984James Dong
134b72081966da3842e27f88045cfa5a67cef3d4220James Dong    // Adjust other track media clock (presumably wall clock)
135b72081966da3842e27f88045cfa5a67cef3d4220James Dong    // based on audio track media clock with the drift time.
136b72081966da3842e27f88045cfa5a67cef3d4220James Dong    int64_t mDriftTimeUs;
1374c23815c3986e50f0cfad3976d748e600f1befa2James Dong    void setDriftTimeUs(int64_t driftTimeUs);
138b72081966da3842e27f88045cfa5a67cef3d4220James Dong    int64_t getDriftTimeUs();
139b72081966da3842e27f88045cfa5a67cef3d4220James Dong
1407755cdd69690ccbb42c6fd47b3e9c4594d4ade82James Dong    // Return whether the nal length is 4 bytes or 2 bytes
1417755cdd69690ccbb42c6fd47b3e9c4594d4ade82James Dong    // Only makes sense for H.264/AVC
1427755cdd69690ccbb42c6fd47b3e9c4594d4ade82James Dong    bool useNalLengthFour();
1437755cdd69690ccbb42c6fd47b3e9c4594d4ade82James Dong
1443300e9667e3daa374659b4a8b97dd92c4d34e501James Dong    void lock();
1453300e9667e3daa374659b4a8b97dd92c4d34e501James Dong    void unlock();
1463300e9667e3daa374659b4a8b97dd92c4d34e501James Dong
1473300e9667e3daa374659b4a8b97dd92c4d34e501James Dong    // Acquire lock before calling these methods
1483300e9667e3daa374659b4a8b97dd92c4d34e501James Dong    off_t addSample_l(MediaBuffer *buffer);
1493300e9667e3daa374659b4a8b97dd92c4d34e501James Dong    off_t addLengthPrefixedSample_l(MediaBuffer *buffer);
150e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
151b5e742397d4129e191d65d51da55302b504f3c99James Dong    inline size_t write(const void *ptr, size_t size, size_t nmemb, FILE* stream);
1521824486e044f4f09640fbd7bef74a20e4efb35aeJames Dong    bool exceedsFileSizeLimit();
153cb7e65c6cbe75c3fe55af95eba73431394669692James Dong    bool use32BitFileOffset() const;
1541824486e044f4f09640fbd7bef74a20e4efb35aeJames Dong    bool exceedsFileDurationLimit();
15522b37fa6e0d7abbfa373e5fdf057fc6dcb2474ffJames Dong    bool isFileStreamable() const;
15685edea79583eb486c8c5c51595a95ddc4ad217f0James Dong    void trackProgressStatus(const Track* track, int64_t timeUs, status_t err = OK);
15765a73f4e8c79d05c0d9001b660325748d4ecf37bJames Dong    void writeCompositionMatrix(int32_t degrees);
158b5e742397d4129e191d65d51da55302b504f3c99James Dong
159e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MPEG4Writer(const MPEG4Writer &);
160e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber    MPEG4Writer &operator=(const MPEG4Writer &);
161e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber};
162e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
163e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}  // namespace android
164e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber
165e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#endif  // MPEG4_WRITER_H_
166