Andreas Huber | e46b7be | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 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 | |
Andreas Huber | 996dddf | 2010-01-25 15:30:31 -0800 | [diff] [blame] | 23 | #include <media/stagefright/MediaWriter.h> |
Andreas Huber | e46b7be | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 24 | #include <utils/List.h> |
Andreas Huber | e46b7be | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 25 | #include <utils/threads.h> |
| 26 | |
| 27 | namespace android { |
| 28 | |
| 29 | class MediaBuffer; |
| 30 | class MediaSource; |
| 31 | class MetaData; |
| 32 | |
Andreas Huber | 996dddf | 2010-01-25 15:30:31 -0800 | [diff] [blame] | 33 | class MPEG4Writer : public MediaWriter { |
Andreas Huber | e46b7be | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 34 | public: |
| 35 | MPEG4Writer(const char *filename); |
Andreas Huber | ea6a38c | 2009-11-16 15:43:38 -0800 | [diff] [blame] | 36 | MPEG4Writer(int fd); |
Andreas Huber | e46b7be | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 37 | |
Andreas Huber | 996dddf | 2010-01-25 15:30:31 -0800 | [diff] [blame] | 38 | virtual status_t addSource(const sp<MediaSource> &source); |
James Dong | 6feaa46 | 2010-06-20 08:20:54 -0700 | [diff] [blame] | 39 | virtual status_t start(MetaData *param = NULL); |
James Dong | d036662 | 2010-08-18 19:10:39 -0700 | [diff] [blame] | 40 | virtual status_t stop(); |
| 41 | virtual status_t pause(); |
Andreas Huber | 996dddf | 2010-01-25 15:30:31 -0800 | [diff] [blame] | 42 | virtual bool reachedEOS(); |
James Dong | 3f51fa7 | 2010-08-18 03:32:26 -0700 | [diff] [blame] | 43 | virtual status_t dump(int fd, const Vector<String16>& args); |
Andreas Huber | e46b7be | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 44 | |
| 45 | void beginBox(const char *fourcc); |
| 46 | void writeInt8(int8_t x); |
| 47 | void writeInt16(int16_t x); |
| 48 | void writeInt32(int32_t x); |
| 49 | void writeInt64(int64_t x); |
| 50 | void writeCString(const char *s); |
| 51 | void writeFourcc(const char *fourcc); |
| 52 | void write(const void *data, size_t size); |
| 53 | void endBox(); |
James Dong | 3300e96 | 2010-04-21 16:14:15 -0700 | [diff] [blame] | 54 | uint32_t interleaveDuration() const { return mInterleaveDurationUs; } |
| 55 | status_t setInterleaveDuration(uint32_t duration); |
James Dong | 52d13f0 | 2010-07-02 11:39:06 -0700 | [diff] [blame] | 56 | int32_t getTimeScale() const { return mTimeScale; } |
Andreas Huber | e46b7be | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 57 | |
Andreas Huber | be06d26 | 2009-08-14 14:37:10 -0700 | [diff] [blame] | 58 | protected: |
| 59 | virtual ~MPEG4Writer(); |
| 60 | |
Andreas Huber | e46b7be | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 61 | private: |
| 62 | class Track; |
| 63 | |
James Dong | b1262a8 | 2010-11-16 14:04:54 -0800 | [diff] [blame] | 64 | int mFd; |
James Dong | 2747e0e | 2010-11-18 20:59:13 -0800 | [diff] [blame] | 65 | status_t mInitCheck; |
James Dong | 7755cdd | 2010-09-02 10:49:55 -0700 | [diff] [blame] | 66 | bool mUse4ByteNalLength; |
James Dong | 39a0b21 | 2010-06-23 00:18:40 -0700 | [diff] [blame] | 67 | bool mUse32BitOffset; |
James Dong | 6a9e39a | 2010-10-04 16:41:53 -0700 | [diff] [blame] | 68 | bool mIsFileSizeLimitExplicitlyRequested; |
James Dong | 08c7473 | 2010-06-10 12:28:15 -0700 | [diff] [blame] | 69 | bool mPaused; |
| 70 | bool mStarted; |
James Dong | b1262a8 | 2010-11-16 14:04:54 -0800 | [diff] [blame] | 71 | off64_t mOffset; |
Andreas Huber | e46b7be | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 72 | off_t mMdatOffset; |
James Dong | b5e7423 | 2010-05-07 10:26:24 -0700 | [diff] [blame] | 73 | uint8_t *mMoovBoxBuffer; |
James Dong | b1262a8 | 2010-11-16 14:04:54 -0800 | [diff] [blame] | 74 | off64_t mMoovBoxBufferOffset; |
James Dong | b5e7423 | 2010-05-07 10:26:24 -0700 | [diff] [blame] | 75 | bool mWriteMoovBoxToMemory; |
James Dong | b1262a8 | 2010-11-16 14:04:54 -0800 | [diff] [blame] | 76 | off64_t mFreeBoxOffset; |
James Dong | b5e7423 | 2010-05-07 10:26:24 -0700 | [diff] [blame] | 77 | bool mStreamableFile; |
James Dong | b1262a8 | 2010-11-16 14:04:54 -0800 | [diff] [blame] | 78 | off64_t mEstimatedMoovBoxSize; |
James Dong | 3300e96 | 2010-04-21 16:14:15 -0700 | [diff] [blame] | 79 | uint32_t mInterleaveDurationUs; |
James Dong | 52d13f0 | 2010-07-02 11:39:06 -0700 | [diff] [blame] | 80 | int32_t mTimeScale; |
James Dong | 9db798d | 2010-05-13 11:47:36 -0700 | [diff] [blame] | 81 | int64_t mStartTimestampUs; |
James Dong | da8073c | 2010-07-30 17:41:22 -0700 | [diff] [blame] | 82 | |
Andreas Huber | e46b7be | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 83 | Mutex mLock; |
| 84 | |
| 85 | List<Track *> mTracks; |
| 86 | |
James Dong | b1262a8 | 2010-11-16 14:04:54 -0800 | [diff] [blame] | 87 | List<off64_t> mBoxes; |
Andreas Huber | e46b7be | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 88 | |
James Dong | 36e573b | 2010-06-19 09:04:18 -0700 | [diff] [blame] | 89 | void setStartTimestampUs(int64_t timeUs); |
| 90 | int64_t getStartTimestampUs(); // Not const |
James Dong | 09936ed | 2010-06-24 19:04:27 -0700 | [diff] [blame] | 91 | status_t startTracks(MetaData *params); |
James Dong | b54a9178 | 2010-06-22 11:27:37 -0700 | [diff] [blame] | 92 | size_t numTracks(); |
James Dong | 6feaa46 | 2010-06-20 08:20:54 -0700 | [diff] [blame] | 93 | int64_t estimateMoovBoxSize(int32_t bitRate); |
James Dong | 9db798d | 2010-05-13 11:47:36 -0700 | [diff] [blame] | 94 | |
James Dong | da8073c | 2010-07-30 17:41:22 -0700 | [diff] [blame] | 95 | struct Chunk { |
| 96 | Track *mTrack; // Owner |
| 97 | int64_t mTimeStampUs; // Timestamp of the 1st sample |
| 98 | List<MediaBuffer *> mSamples; // Sample data |
| 99 | |
| 100 | // Convenient constructor |
James Dong | f6a2bff | 2011-02-09 14:00:55 -0800 | [diff] [blame] | 101 | Chunk(): mTrack(NULL), mTimeStampUs(0) {} |
| 102 | |
James Dong | da8073c | 2010-07-30 17:41:22 -0700 | [diff] [blame] | 103 | Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples) |
| 104 | : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) { |
| 105 | } |
| 106 | |
| 107 | }; |
| 108 | struct ChunkInfo { |
| 109 | Track *mTrack; // Owner |
| 110 | List<Chunk> mChunks; // Remaining chunks to be written |
| 111 | }; |
| 112 | |
| 113 | bool mIsFirstChunk; |
| 114 | volatile bool mDone; // Writer thread is done? |
| 115 | pthread_t mThread; // Thread id for the writer |
| 116 | List<ChunkInfo> mChunkInfos; // Chunk infos |
| 117 | Condition mChunkReadyCondition; // Signal that chunks are available |
| 118 | |
| 119 | // Writer thread handling |
| 120 | status_t startWriterThread(); |
| 121 | void stopWriterThread(); |
| 122 | static void *ThreadWrapper(void *me); |
| 123 | void threadFunc(); |
| 124 | |
| 125 | // Buffer a single chunk to be written out later. |
| 126 | void bufferChunk(const Chunk& chunk); |
| 127 | |
| 128 | // Write all buffered chunks from all tracks |
James Dong | f6a2bff | 2011-02-09 14:00:55 -0800 | [diff] [blame] | 129 | void writeAllChunks(); |
James Dong | da8073c | 2010-07-30 17:41:22 -0700 | [diff] [blame] | 130 | |
James Dong | f6a2bff | 2011-02-09 14:00:55 -0800 | [diff] [blame] | 131 | // Retrieve the proper chunk to write if there is one |
| 132 | // Return true if a chunk is found; otherwise, return false. |
| 133 | bool findChunkToWrite(Chunk *chunk); |
James Dong | da8073c | 2010-07-30 17:41:22 -0700 | [diff] [blame] | 134 | |
James Dong | f6a2bff | 2011-02-09 14:00:55 -0800 | [diff] [blame] | 135 | // Actually write the given chunk to the file. |
| 136 | void writeChunkToFile(Chunk* chunk); |
James Dong | da8073c | 2010-07-30 17:41:22 -0700 | [diff] [blame] | 137 | |
James Dong | b720819 | 2010-08-02 19:13:40 -0700 | [diff] [blame] | 138 | // Adjust other track media clock (presumably wall clock) |
| 139 | // based on audio track media clock with the drift time. |
| 140 | int64_t mDriftTimeUs; |
James Dong | 4c23815 | 2010-09-01 18:48:35 -0700 | [diff] [blame] | 141 | void setDriftTimeUs(int64_t driftTimeUs); |
James Dong | b720819 | 2010-08-02 19:13:40 -0700 | [diff] [blame] | 142 | int64_t getDriftTimeUs(); |
| 143 | |
James Dong | 7755cdd | 2010-09-02 10:49:55 -0700 | [diff] [blame] | 144 | // Return whether the nal length is 4 bytes or 2 bytes |
| 145 | // Only makes sense for H.264/AVC |
| 146 | bool useNalLengthFour(); |
| 147 | |
James Dong | 3300e96 | 2010-04-21 16:14:15 -0700 | [diff] [blame] | 148 | void lock(); |
| 149 | void unlock(); |
| 150 | |
| 151 | // Acquire lock before calling these methods |
James Dong | b1262a8 | 2010-11-16 14:04:54 -0800 | [diff] [blame] | 152 | off64_t addSample_l(MediaBuffer *buffer); |
| 153 | off64_t addLengthPrefixedSample_l(MediaBuffer *buffer); |
Andreas Huber | e46b7be | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 154 | |
James Dong | 2747e0e | 2010-11-18 20:59:13 -0800 | [diff] [blame] | 155 | inline size_t write(const void *ptr, size_t size, size_t nmemb); |
James Dong | 1824486 | 2010-05-11 14:57:02 -0700 | [diff] [blame] | 156 | bool exceedsFileSizeLimit(); |
James Dong | cb7e65c | 2010-09-02 11:19:11 -0700 | [diff] [blame] | 157 | bool use32BitFileOffset() const; |
James Dong | 1824486 | 2010-05-11 14:57:02 -0700 | [diff] [blame] | 158 | bool exceedsFileDurationLimit(); |
James Dong | 22b37fa | 2010-10-19 21:28:47 -0700 | [diff] [blame] | 159 | bool isFileStreamable() const; |
James Dong | 7fc8b4f | 2011-03-18 11:25:41 -0700 | [diff] [blame^] | 160 | void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK); |
James Dong | b9d7e01 | 2010-11-09 11:15:47 -0800 | [diff] [blame] | 161 | void writeCompositionMatrix(int32_t degrees); |
James Dong | b5e7423 | 2010-05-07 10:26:24 -0700 | [diff] [blame] | 162 | |
Andreas Huber | e46b7be | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 163 | MPEG4Writer(const MPEG4Writer &); |
| 164 | MPEG4Writer &operator=(const MPEG4Writer &); |
| 165 | }; |
| 166 | |
| 167 | } // namespace android |
| 168 | |
| 169 | #endif // MPEG4_WRITER_H_ |