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     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