Home | History | Annotate | Download | only in stagefright
      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);
     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();
     62     uint32_t interleaveDuration() const { return mInterleaveDurationUs; }
     63     status_t setInterleaveDuration(uint32_t duration);
     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();
     70     virtual void setStartTimeOffsetMs(int ms) { mStartTimeOffsetMs = ms; }
     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     enum {
     86         kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
     87     };
     88 
     89     int  mFd;
     90     int mNextFd;
     91     sp<MetaData> mStartMeta;
     92     status_t mInitCheck;
     93     bool mIsRealTimeRecording;
     94     bool mUse4ByteNalLength;
     95     bool mUse32BitOffset;
     96     bool mIsFileSizeLimitExplicitlyRequested;
     97     bool mPaused;
     98     bool mStarted;  // Writer thread + track threads started successfully
     99     bool mWriterThreadStarted;  // Only writer thread started successfully
    100     bool mSendNotify;
    101     off64_t mOffset;
    102     off_t mMdatOffset;
    103     uint8_t *mInMemoryCache;
    104     off64_t mInMemoryCacheOffset;
    105     off64_t mInMemoryCacheSize;
    106     bool  mWriteBoxToMemory;
    107     off64_t mFreeBoxOffset;
    108     bool mStreamableFile;
    109     off64_t mMoovExtraSize;
    110     uint32_t mInterleaveDurationUs;
    111     int32_t mTimeScale;
    112     int64_t mStartTimestampUs;
    113     int mLatitudex10000;
    114     int mLongitudex10000;
    115     bool mAreGeoTagsAvailable;
    116     int32_t mStartTimeOffsetMs;
    117     bool mSwitchPending;
    118 
    119     sp<ALooper> mLooper;
    120     sp<AHandlerReflector<MPEG4Writer> > mReflector;
    121 
    122     Mutex mLock;
    123 
    124     List<Track *> mTracks;
    125 
    126     List<off64_t> mBoxes;
    127 
    128     sp<AMessage> mMetaKeys;
    129 
    130     void setStartTimestampUs(int64_t timeUs);
    131     int64_t getStartTimestampUs();  // Not const
    132     status_t startTracks(MetaData *params);
    133     size_t numTracks();
    134     int64_t estimateMoovBoxSize(int32_t bitRate);
    135     int64_t estimateFileLevelMetaSize(MetaData *params);
    136     void writeCachedBoxToFile(const char *type);
    137 
    138     struct Chunk {
    139         Track               *mTrack;        // Owner
    140         int64_t             mTimeStampUs;   // Timestamp of the 1st sample
    141         List<MediaBuffer *> mSamples;       // Sample data
    142 
    143         // Convenient constructor
    144         Chunk(): mTrack(NULL), mTimeStampUs(0) {}
    145 
    146         Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples)
    147             : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) {
    148         }
    149 
    150     };
    151     struct ChunkInfo {
    152         Track               *mTrack;        // Owner
    153         List<Chunk>         mChunks;        // Remaining chunks to be written
    154 
    155         // Previous chunk timestamp that has been written
    156         int64_t mPrevChunkTimestampUs;
    157 
    158         // Max time interval between neighboring chunks
    159         int64_t mMaxInterChunkDurUs;
    160 
    161     };
    162 
    163     bool            mIsFirstChunk;
    164     volatile bool   mDone;                  // Writer thread is done?
    165     pthread_t       mThread;                // Thread id for the writer
    166     List<ChunkInfo> mChunkInfos;            // Chunk infos
    167     Condition       mChunkReadyCondition;   // Signal that chunks are available
    168 
    169     // HEIF writing
    170     typedef key_value_pair_t< const char *, Vector<uint16_t> > ItemRefs;
    171     typedef struct _ItemInfo {
    172         bool isGrid() const { return !strcmp("grid", itemType); }
    173         bool isImage() const { return !strcmp("hvc1", itemType) || isGrid(); }
    174         const char *itemType;
    175         uint16_t itemId;
    176         bool isPrimary;
    177         bool isHidden;
    178         union {
    179             // image item
    180             struct {
    181                 uint32_t offset;
    182                 uint32_t size;
    183             };
    184             // grid item
    185             struct {
    186                 uint32_t rows;
    187                 uint32_t cols;
    188                 uint32_t width;
    189                 uint32_t height;
    190             };
    191         };
    192         Vector<uint16_t> properties;
    193         Vector<ItemRefs> refsList;
    194     } ItemInfo;
    195 
    196     typedef struct _ItemProperty {
    197         uint32_t type;
    198         int32_t width;
    199         int32_t height;
    200         int32_t rotation;
    201         sp<ABuffer> hvcc;
    202     } ItemProperty;
    203 
    204     bool mHasFileLevelMeta;
    205     bool mHasMoovBox;
    206     uint32_t mPrimaryItemId;
    207     uint32_t mAssociationEntryCount;
    208     uint32_t mNumGrids;
    209     bool mHasRefs;
    210     Vector<ItemInfo> mItems;
    211     Vector<ItemProperty> mProperties;
    212 
    213     // Writer thread handling
    214     status_t startWriterThread();
    215     void stopWriterThread();
    216     static void *ThreadWrapper(void *me);
    217     void threadFunc();
    218 
    219     // Buffer a single chunk to be written out later.
    220     void bufferChunk(const Chunk& chunk);
    221 
    222     // Write all buffered chunks from all tracks
    223     void writeAllChunks();
    224 
    225     // Retrieve the proper chunk to write if there is one
    226     // Return true if a chunk is found; otherwise, return false.
    227     bool findChunkToWrite(Chunk *chunk);
    228 
    229     // Actually write the given chunk to the file.
    230     void writeChunkToFile(Chunk* chunk);
    231 
    232     // Adjust other track media clock (presumably wall clock)
    233     // based on audio track media clock with the drift time.
    234     int64_t mDriftTimeUs;
    235     void setDriftTimeUs(int64_t driftTimeUs);
    236     int64_t getDriftTimeUs();
    237 
    238     // Return whether the nal length is 4 bytes or 2 bytes
    239     // Only makes sense for H.264/AVC
    240     bool useNalLengthFour();
    241 
    242     // Return whether the writer is used for real time recording.
    243     // In real time recording mode, new samples will be allowed to buffered into
    244     // chunks in higher priority thread, even though the file writer has not
    245     // drained the chunks yet.
    246     // By default, real time recording is on.
    247     bool isRealTimeRecording() const;
    248 
    249     void lock();
    250     void unlock();
    251 
    252     // Init all the internal variables for each recording session. Some variables
    253     // will only need to be set for the first recording session and they will stay
    254     // the same across all the recording sessions.
    255     void initInternal(int fd, bool isFirstSession);
    256 
    257     // Acquire lock before calling these methods
    258     off64_t addSample_l(MediaBuffer *buffer, bool usePrefix, bool isExif, 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