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 
23 #include <media/stagefright/MediaWriter.h>
24 #include <utils/List.h>
25 #include <utils/threads.h>
26 #include <media/stagefright/foundation/AHandlerReflector.h>
27 #include <media/stagefright/foundation/ALooper.h>
28 
29 namespace android {
30 
31 struct AMessage;
32 class MediaBuffer;
33 struct ABuffer;
34 
35 class MPEG4Writer : public MediaWriter {
36 public:
37     MPEG4Writer(int fd);
38 
39     // Limitations
40     // No more than one video and/or one audio source can be added, but
41     // multiple metadata sources can be added.
42     virtual status_t addSource(const sp<MediaSource> &source);
43 
44     // Returns INVALID_OPERATION if there is no source or track.
45     virtual status_t start(MetaData *param = NULL);
stop()46     virtual status_t stop() { return reset(); }
47     virtual status_t pause();
48     virtual bool reachedEOS();
49     virtual status_t dump(int fd, const Vector<String16>& args);
50 
51     void beginBox(const char *fourcc);
52     void beginBox(uint32_t id);
53     void writeInt8(int8_t x);
54     void writeInt16(int16_t x);
55     void writeInt32(int32_t x);
56     void writeInt64(int64_t x);
57     void writeCString(const char *s);
58     void writeFourcc(const char *fourcc);
59     void write(const void *data, size_t size);
60     inline size_t write(const void *ptr, size_t size, size_t nmemb);
61     void endBox();
interleaveDuration()62     uint32_t interleaveDuration() const { return mInterleaveDurationUs; }
63     status_t setInterleaveDuration(uint32_t duration);
getTimeScale()64     int32_t getTimeScale() const { return mTimeScale; }
65 
66     status_t setGeoData(int latitudex10000, int longitudex10000);
67     status_t setCaptureRate(float captureFps);
68     status_t setTemporalLayerCount(uint32_t layerCount);
69     void notifyApproachingLimit();
setStartTimeOffsetMs(int ms)70     virtual void setStartTimeOffsetMs(int ms) { mStartTimeOffsetMs = ms; }
getStartTimeOffsetMs()71     virtual int32_t getStartTimeOffsetMs() const { return mStartTimeOffsetMs; }
72     virtual status_t setNextFd(int fd);
73 
74 protected:
75     virtual ~MPEG4Writer();
76 
77 private:
78     class Track;
79     friend struct AHandlerReflector<MPEG4Writer>;
80 
81     enum {
82         kWhatSwitch                          = 'swch',
83     };
84 
85     int  mFd;
86     int mNextFd;
87     sp<MetaData> mStartMeta;
88     status_t mInitCheck;
89     bool mIsRealTimeRecording;
90     bool mUse4ByteNalLength;
91     bool mUse32BitOffset;
92     bool mIsFileSizeLimitExplicitlyRequested;
93     bool mPaused;
94     bool mStarted;  // Writer thread + track threads started successfully
95     bool mWriterThreadStarted;  // Only writer thread started successfully
96     bool mSendNotify;
97     off64_t mOffset;
98     off_t mMdatOffset;
99     uint8_t *mInMemoryCache;
100     off64_t mInMemoryCacheOffset;
101     off64_t mInMemoryCacheSize;
102     bool  mWriteBoxToMemory;
103     off64_t mFreeBoxOffset;
104     bool mStreamableFile;
105     off64_t mMoovExtraSize;
106     uint32_t mInterleaveDurationUs;
107     int32_t mTimeScale;
108     int64_t mStartTimestampUs;
109     int32_t mStartTimeOffsetBFramesUs; // Start time offset when B Frames are present
110     int mLatitudex10000;
111     int mLongitudex10000;
112     bool mAreGeoTagsAvailable;
113     int32_t mStartTimeOffsetMs;
114     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     int32_t getStartTimeOffsetBFramesUs();
130     status_t startTracks(MetaData *params);
131     size_t numTracks();
132     int64_t estimateMoovBoxSize(int32_t bitRate);
133     int64_t estimateFileLevelMetaSize(MetaData *params);
134     void writeCachedBoxToFile(const char *type);
135 
136     struct Chunk {
137         Track               *mTrack;        // Owner
138         int64_t             mTimeStampUs;   // Timestamp of the 1st sample
139         List<MediaBuffer *> mSamples;       // Sample data
140 
141         // Convenient constructor
142         Chunk(): mTrack(NULL), mTimeStampUs(0) {}
143 
144         Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples)
145             : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) {
146         }
147 
148     };
149     struct ChunkInfo {
150         Track               *mTrack;        // Owner
151         List<Chunk>         mChunks;        // Remaining chunks to be written
152 
153         // Previous chunk timestamp that has been written
154         int64_t mPrevChunkTimestampUs;
155 
156         // Max time interval between neighboring chunks
157         int64_t mMaxInterChunkDurUs;
158 
159     };
160 
161     bool            mIsFirstChunk;
162     volatile bool   mDone;                  // Writer thread is done?
163     pthread_t       mThread;                // Thread id for the writer
164     List<ChunkInfo> mChunkInfos;            // Chunk infos
165     Condition       mChunkReadyCondition;   // Signal that chunks are available
166 
167     // HEIF writing
168     typedef key_value_pair_t< const char *, Vector<uint16_t> > ItemRefs;
169     typedef struct _ItemInfo {
170         bool isGrid() const { return !strcmp("grid", itemType); }
171         bool isImage() const { return !strcmp("hvc1", itemType) || isGrid(); }
172         const char *itemType;
173         uint16_t itemId;
174         bool isPrimary;
175         bool isHidden;
176         union {
177             // image item
178             struct {
179                 uint32_t offset;
180                 uint32_t size;
181             };
182             // grid item
183             struct {
184                 uint32_t rows;
185                 uint32_t cols;
186                 uint32_t width;
187                 uint32_t height;
188             };
189         };
190         Vector<uint16_t> properties;
191         Vector<ItemRefs> refsList;
192     } ItemInfo;
193 
194     typedef struct _ItemProperty {
195         uint32_t type;
196         int32_t width;
197         int32_t height;
198         int32_t rotation;
199         sp<ABuffer> hvcc;
200     } ItemProperty;
201 
202     bool mHasFileLevelMeta;
203     bool mHasMoovBox;
204     uint32_t mPrimaryItemId;
205     uint32_t mAssociationEntryCount;
206     uint32_t mNumGrids;
207     bool mHasRefs;
208     Vector<ItemInfo> mItems;
209     Vector<ItemProperty> mProperties;
210 
211     // Writer thread handling
212     status_t startWriterThread();
213     void stopWriterThread();
214     static void *ThreadWrapper(void *me);
215     void threadFunc();
216 
217     // Buffer a single chunk to be written out later.
218     void bufferChunk(const Chunk& chunk);
219 
220     // Write all buffered chunks from all tracks
221     void writeAllChunks();
222 
223     // Retrieve the proper chunk to write if there is one
224     // Return true if a chunk is found; otherwise, return false.
225     bool findChunkToWrite(Chunk *chunk);
226 
227     // Actually write the given chunk to the file.
228     void writeChunkToFile(Chunk* chunk);
229 
230     // Adjust other track media clock (presumably wall clock)
231     // based on audio track media clock with the drift time.
232     int64_t mDriftTimeUs;
233     void setDriftTimeUs(int64_t driftTimeUs);
234     int64_t getDriftTimeUs();
235 
236     // Return whether the nal length is 4 bytes or 2 bytes
237     // Only makes sense for H.264/AVC
238     bool useNalLengthFour();
239 
240     // Return whether the writer is used for real time recording.
241     // In real time recording mode, new samples will be allowed to buffered into
242     // chunks in higher priority thread, even though the file writer has not
243     // drained the chunks yet.
244     // By default, real time recording is on.
245     bool isRealTimeRecording() const;
246 
247     void lock();
248     void unlock();
249 
250     // Init all the internal variables for each recording session. Some variables
251     // will only need to be set for the first recording session and they will stay
252     // the same across all the recording sessions.
253     void initInternal(int fd, bool isFirstSession);
254 
255     // Acquire lock before calling these methods
256     off64_t addSample_l(
257             MediaBuffer *buffer, bool usePrefix,
258             uint32_t tiffHdrOffset, size_t *bytesWritten);
259     void addLengthPrefixedSample_l(MediaBuffer *buffer);
260     void addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer);
261     uint16_t addProperty_l(const ItemProperty &);
262     uint16_t addItem_l(const ItemInfo &);
263     void addRefs_l(uint16_t itemId, const ItemRefs &);
264 
265     bool exceedsFileSizeLimit();
266     bool use32BitFileOffset() const;
267     bool exceedsFileDurationLimit();
268     bool approachingFileSizeLimit();
269     bool isFileStreamable() const;
270     void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK);
271     void writeCompositionMatrix(int32_t degrees);
272     void writeMvhdBox(int64_t durationUs);
273     void writeMoovBox(int64_t durationUs);
274     void writeFtypBox(MetaData *param);
275     void writeUdtaBox();
276     void writeGeoDataBox();
277     void writeLatitude(int degreex10000);
278     void writeLongitude(int degreex10000);
279     void finishCurrentSession();
280 
281     void addDeviceMeta();
282     void writeHdlr(const char *handlerType);
283     void writeKeys();
284     void writeIlst();
285     void writeMoovLevelMetaBox();
286 
287     // HEIF writing
288     void writeIlocBox();
289     void writeInfeBox(uint16_t itemId, const char *type, uint32_t flags);
290     void writeIinfBox();
291     void writeIpcoBox();
292     void writeIpmaBox();
293     void writeIprpBox();
294     void writeIdatBox();
295     void writeIrefBox();
296     void writePitmBox();
297     void writeFileLevelMetaBox();
298 
299     void sendSessionSummary();
300     void release();
301     status_t switchFd();
302     status_t reset(bool stopSource = true);
303 
304     static uint32_t getMpeg4Time();
305 
306     void onMessageReceived(const sp<AMessage> &msg);
307 
308     MPEG4Writer(const MPEG4Writer &);
309     MPEG4Writer &operator=(const MPEG4Writer &);
310 };
311 
312 }  // namespace android
313 
314 #endif  // MPEG4_WRITER_H_
315