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/IMediaSource.h>
     24 #include <media/stagefright/MediaWriter.h>
     25 #include <utils/List.h>
     26 #include <utils/threads.h>
     27 #include <media/stagefright/foundation/AHandlerReflector.h>
     28 #include <media/stagefright/foundation/ALooper.h>
     29 
     30 namespace android {
     31 
     32 struct AMessage;
     33 class MediaBuffer;
     34 class MetaData;
     35 
     36 class MPEG4Writer : public MediaWriter {
     37 public:
     38     MPEG4Writer(int fd);
     39 
     40     // Limitations
     41     // No more than one video and/or one audio source can be added, but
     42     // multiple metadata sources can be added.
     43     virtual status_t addSource(const sp<IMediaSource> &source);
     44 
     45     // Returns INVALID_OPERATION if there is no source or track.
     46     virtual status_t start(MetaData *param = NULL);
     47     virtual status_t stop() { return reset(); }
     48     virtual status_t pause();
     49     virtual bool reachedEOS();
     50     virtual status_t dump(int fd, const Vector<String16>& args);
     51 
     52     void beginBox(const char *fourcc);
     53     void beginBox(uint32_t id);
     54     void writeInt8(int8_t x);
     55     void writeInt16(int16_t x);
     56     void writeInt32(int32_t x);
     57     void writeInt64(int64_t x);
     58     void writeCString(const char *s);
     59     void writeFourcc(const char *fourcc);
     60     void write(const void *data, size_t size);
     61     inline size_t write(const void *ptr, size_t size, size_t nmemb);
     62     void endBox();
     63     uint32_t interleaveDuration() const { return mInterleaveDurationUs; }
     64     status_t setInterleaveDuration(uint32_t duration);
     65     int32_t getTimeScale() const { return mTimeScale; }
     66 
     67     status_t setGeoData(int latitudex10000, int longitudex10000);
     68     status_t setCaptureRate(float captureFps);
     69     status_t setTemporalLayerCount(uint32_t layerCount);
     70     void notifyApproachingLimit();
     71     virtual void setStartTimeOffsetMs(int ms) { mStartTimeOffsetMs = ms; }
     72     virtual int32_t getStartTimeOffsetMs() const { return mStartTimeOffsetMs; }
     73     virtual status_t setNextFd(int fd);
     74 
     75 protected:
     76     virtual ~MPEG4Writer();
     77 
     78 private:
     79     class Track;
     80     friend struct AHandlerReflector<MPEG4Writer>;
     81 
     82     enum {
     83         kWhatSwitch                          = 'swch',
     84     };
     85 
     86     enum {
     87         kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
     88     };
     89 
     90     int  mFd;
     91     int mNextFd;
     92     sp<MetaData> mStartMeta;
     93     status_t mInitCheck;
     94     bool mIsRealTimeRecording;
     95     bool mUse4ByteNalLength;
     96     bool mUse32BitOffset;
     97     bool mIsFileSizeLimitExplicitlyRequested;
     98     bool mPaused;
     99     bool mStarted;  // Writer thread + track threads started successfully
    100     bool mWriterThreadStarted;  // Only writer thread started successfully
    101     bool mSendNotify;
    102     off64_t mOffset;
    103     off_t mMdatOffset;
    104     uint8_t *mMoovBoxBuffer;
    105     off64_t mMoovBoxBufferOffset;
    106     bool  mWriteMoovBoxToMemory;
    107     off64_t mFreeBoxOffset;
    108     bool mStreamableFile;
    109     off64_t mEstimatedMoovBoxSize;
    110     off64_t mMoovExtraSize;
    111     uint32_t mInterleaveDurationUs;
    112     int32_t mTimeScale;
    113     int64_t mStartTimestampUs;
    114     int mLatitudex10000;
    115     int mLongitudex10000;
    116     bool mAreGeoTagsAvailable;
    117     int32_t mStartTimeOffsetMs;
    118     bool mSwitchPending;
    119 
    120     sp<ALooper> mLooper;
    121     sp<AHandlerReflector<MPEG4Writer> > mReflector;
    122 
    123     Mutex mLock;
    124 
    125     List<Track *> mTracks;
    126 
    127     List<off64_t> mBoxes;
    128 
    129     sp<AMessage> mMetaKeys;
    130 
    131     void setStartTimestampUs(int64_t timeUs);
    132     int64_t getStartTimestampUs();  // Not const
    133     status_t startTracks(MetaData *params);
    134     size_t numTracks();
    135     int64_t estimateMoovBoxSize(int32_t bitRate);
    136 
    137     struct Chunk {
    138         Track               *mTrack;        // Owner
    139         int64_t             mTimeStampUs;   // Timestamp of the 1st sample
    140         List<MediaBuffer *> mSamples;       // Sample data
    141 
    142         // Convenient constructor
    143         Chunk(): mTrack(NULL), mTimeStampUs(0) {}
    144 
    145         Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples)
    146             : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) {
    147         }
    148 
    149     };
    150     struct ChunkInfo {
    151         Track               *mTrack;        // Owner
    152         List<Chunk>         mChunks;        // Remaining chunks to be written
    153 
    154         // Previous chunk timestamp that has been written
    155         int64_t mPrevChunkTimestampUs;
    156 
    157         // Max time interval between neighboring chunks
    158         int64_t mMaxInterChunkDurUs;
    159 
    160     };
    161 
    162     bool            mIsFirstChunk;
    163     volatile bool   mDone;                  // Writer thread is done?
    164     pthread_t       mThread;                // Thread id for the writer
    165     List<ChunkInfo> mChunkInfos;            // Chunk infos
    166     Condition       mChunkReadyCondition;   // Signal that chunks are available
    167 
    168     // Writer thread handling
    169     status_t startWriterThread();
    170     void stopWriterThread();
    171     static void *ThreadWrapper(void *me);
    172     void threadFunc();
    173 
    174     // Buffer a single chunk to be written out later.
    175     void bufferChunk(const Chunk& chunk);
    176 
    177     // Write all buffered chunks from all tracks
    178     void writeAllChunks();
    179 
    180     // Retrieve the proper chunk to write if there is one
    181     // Return true if a chunk is found; otherwise, return false.
    182     bool findChunkToWrite(Chunk *chunk);
    183 
    184     // Actually write the given chunk to the file.
    185     void writeChunkToFile(Chunk* chunk);
    186 
    187     // Adjust other track media clock (presumably wall clock)
    188     // based on audio track media clock with the drift time.
    189     int64_t mDriftTimeUs;
    190     void setDriftTimeUs(int64_t driftTimeUs);
    191     int64_t getDriftTimeUs();
    192 
    193     // Return whether the nal length is 4 bytes or 2 bytes
    194     // Only makes sense for H.264/AVC
    195     bool useNalLengthFour();
    196 
    197     // Return whether the writer is used for real time recording.
    198     // In real time recording mode, new samples will be allowed to buffered into
    199     // chunks in higher priority thread, even though the file writer has not
    200     // drained the chunks yet.
    201     // By default, real time recording is on.
    202     bool isRealTimeRecording() const;
    203 
    204     void lock();
    205     void unlock();
    206 
    207     // Init all the internal variables for each recording session. Some variables
    208     // will only need to be set for the first recording session and they will stay
    209     // the same across all the recording sessions.
    210     void initInternal(int fd, bool isFirstSession);
    211 
    212     // Acquire lock before calling these methods
    213     off64_t addSample_l(MediaBuffer *buffer);
    214     off64_t addLengthPrefixedSample_l(MediaBuffer *buffer);
    215     off64_t addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer);
    216 
    217     bool exceedsFileSizeLimit();
    218     bool use32BitFileOffset() const;
    219     bool exceedsFileDurationLimit();
    220     bool approachingFileSizeLimit();
    221     bool isFileStreamable() const;
    222     void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK);
    223     void writeCompositionMatrix(int32_t degrees);
    224     void writeMvhdBox(int64_t durationUs);
    225     void writeMoovBox(int64_t durationUs);
    226     void writeFtypBox(MetaData *param);
    227     void writeUdtaBox();
    228     void writeGeoDataBox();
    229     void writeLatitude(int degreex10000);
    230     void writeLongitude(int degreex10000);
    231     void finishCurrentSession();
    232 
    233     void addDeviceMeta();
    234     void writeHdlr();
    235     void writeKeys();
    236     void writeIlst();
    237     void writeMetaBox();
    238     void sendSessionSummary();
    239     void release();
    240     status_t switchFd();
    241     status_t reset(bool stopSource = true);
    242 
    243     static uint32_t getMpeg4Time();
    244 
    245     void onMessageReceived(const sp<AMessage> &msg);
    246 
    247     MPEG4Writer(const MPEG4Writer &);
    248     MPEG4Writer &operator=(const MPEG4Writer &);
    249 };
    250 
    251 }  // namespace android
    252 
    253 #endif  // MPEG4_WRITER_H_
    254