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