Home | History | Annotate | Download | only in libstagefright
      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 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "MPEG4Writer"
     19 #include <utils/Log.h>
     20 
     21 #include <arpa/inet.h>
     22 
     23 #include <pthread.h>
     24 #include <sys/prctl.h>
     25 
     26 #include <media/stagefright/foundation/ADebug.h>
     27 #include <media/stagefright/MPEG4Writer.h>
     28 #include <media/stagefright/MediaBuffer.h>
     29 #include <media/stagefright/MetaData.h>
     30 #include <media/stagefright/MediaDefs.h>
     31 #include <media/stagefright/MediaErrors.h>
     32 #include <media/stagefright/MediaSource.h>
     33 #include <media/stagefright/Utils.h>
     34 #include <media/mediarecorder.h>
     35 #include <cutils/properties.h>
     36 #include <sys/types.h>
     37 #include <sys/stat.h>
     38 #include <fcntl.h>
     39 #include <unistd.h>
     40 
     41 #include "include/ESDS.h"
     42 
     43 namespace android {
     44 
     45 static const int64_t kMax32BitFileSize = 0x007fffffffLL;
     46 static const uint8_t kNalUnitTypeSeqParamSet = 0x07;
     47 static const uint8_t kNalUnitTypePicParamSet = 0x08;
     48 static const int64_t kInitialDelayTimeUs     = 700000LL;
     49 
     50 class MPEG4Writer::Track {
     51 public:
     52     Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
     53 
     54     ~Track();
     55 
     56     status_t start(MetaData *params);
     57     status_t stop();
     58     status_t pause();
     59     bool reachedEOS();
     60 
     61     int64_t getDurationUs() const;
     62     int64_t getEstimatedTrackSizeBytes() const;
     63     void writeTrackHeader(bool use32BitOffset = true);
     64     void bufferChunk(int64_t timestampUs);
     65     bool isAvc() const { return mIsAvc; }
     66     bool isAudio() const { return mIsAudio; }
     67     bool isMPEG4() const { return mIsMPEG4; }
     68     void addChunkOffset(off64_t offset);
     69     int32_t getTrackId() const { return mTrackId; }
     70     status_t dump(int fd, const Vector<String16>& args) const;
     71 
     72 private:
     73     enum {
     74         kMaxCttsOffsetTimeUs = 1000000LL,  // 1 second
     75         kSampleArraySize = 1000,
     76     };
     77 
     78     MPEG4Writer *mOwner;
     79     sp<MetaData> mMeta;
     80     sp<MediaSource> mSource;
     81     volatile bool mDone;
     82     volatile bool mPaused;
     83     volatile bool mResumed;
     84     volatile bool mStarted;
     85     bool mIsAvc;
     86     bool mIsAudio;
     87     bool mIsMPEG4;
     88     int32_t mTrackId;
     89     int64_t mTrackDurationUs;
     90     int64_t mMaxChunkDurationUs;
     91 
     92     bool mIsRealTimeRecording;
     93     int64_t mMaxTimeStampUs;
     94     int64_t mEstimatedTrackSizeBytes;
     95     int64_t mMdatSizeBytes;
     96     int32_t mTimeScale;
     97 
     98     pthread_t mThread;
     99 
    100     /*
    101      * mNumSamples is used to track the total number of samples in
    102      * mSampleSizes List.
    103      *
    104      * A linked list of fixed sized array is used here to reduce the time
    105      * to write out stsz box.
    106      */
    107     uint32_t            mNumSamples;
    108     uint32_t*           mCurrentSampleSizeArr;
    109     List<uint32_t *>    mSampleSizes;
    110     bool                mSamplesHaveSameSize;
    111 
    112     List<MediaBuffer *> mChunkSamples;
    113 
    114     size_t              mNumStcoTableEntries;
    115     List<off64_t>         mChunkOffsets;
    116 
    117     size_t              mNumStscTableEntries;
    118     struct StscTableEntry {
    119 
    120         StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
    121             : firstChunk(chunk),
    122               samplesPerChunk(samples),
    123               sampleDescriptionId(id) {}
    124 
    125         uint32_t firstChunk;
    126         uint32_t samplesPerChunk;
    127         uint32_t sampleDescriptionId;
    128     };
    129     List<StscTableEntry> mStscTableEntries;
    130 
    131     size_t        mNumStssTableEntries;
    132     List<int32_t> mStssTableEntries;
    133 
    134     struct SttsTableEntry {
    135 
    136         SttsTableEntry(uint32_t count, uint32_t duration)
    137             : sampleCount(count), sampleDuration(duration) {}
    138 
    139         uint32_t sampleCount;
    140         uint32_t sampleDuration;  // time scale based
    141     };
    142     size_t        mNumSttsTableEntries;
    143     List<SttsTableEntry> mSttsTableEntries;
    144 
    145     struct CttsTableEntry {
    146         CttsTableEntry(uint32_t count, int32_t timescaledDur)
    147             : sampleCount(count), sampleDuration(timescaledDur) {}
    148 
    149         uint32_t sampleCount;
    150         uint32_t sampleDuration;  // time scale based
    151     };
    152     size_t        mNumCttsTableEntries;
    153     List<CttsTableEntry> mCttsTableEntries;
    154     int64_t mMinCttsOffsetTimeUs;
    155     int64_t mMaxCttsOffsetTimeUs;
    156 
    157     // Sequence parameter set or picture parameter set
    158     struct AVCParamSet {
    159         AVCParamSet(uint16_t length, const uint8_t *data)
    160             : mLength(length), mData(data) {}
    161 
    162         uint16_t mLength;
    163         const uint8_t *mData;
    164     };
    165     List<AVCParamSet> mSeqParamSets;
    166     List<AVCParamSet> mPicParamSets;
    167     uint8_t mProfileIdc;
    168     uint8_t mProfileCompatible;
    169     uint8_t mLevelIdc;
    170 
    171     void *mCodecSpecificData;
    172     size_t mCodecSpecificDataSize;
    173     bool mGotAllCodecSpecificData;
    174     bool mTrackingProgressStatus;
    175 
    176     bool mReachedEOS;
    177     int64_t mStartTimestampUs;
    178     int64_t mStartTimeRealUs;
    179     int64_t mFirstSampleTimeRealUs;
    180     int64_t mPreviousTrackTimeUs;
    181     int64_t mTrackEveryTimeDurationUs;
    182 
    183     // Update the audio track's drift information.
    184     void updateDriftTime(const sp<MetaData>& meta);
    185 
    186     int32_t getStartTimeOffsetScaledTime() const;
    187 
    188     static void *ThreadWrapper(void *me);
    189     status_t threadEntry();
    190 
    191     const uint8_t *parseParamSet(
    192         const uint8_t *data, size_t length, int type, size_t *paramSetLen);
    193 
    194     status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
    195     status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
    196     status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
    197 
    198     // Track authoring progress status
    199     void trackProgressStatus(int64_t timeUs, status_t err = OK);
    200     void initTrackingProgressStatus(MetaData *params);
    201 
    202     void getCodecSpecificDataFromInputFormatIfPossible();
    203 
    204     // Determine the track time scale
    205     // If it is an audio track, try to use the sampling rate as
    206     // the time scale; however, if user chooses the overwrite
    207     // value, the user-supplied time scale will be used.
    208     void setTimeScale();
    209 
    210     // Simple validation on the codec specific data
    211     status_t checkCodecSpecificData() const;
    212     int32_t mRotation;
    213 
    214     void updateTrackSizeEstimate();
    215     void addOneStscTableEntry(size_t chunkId, size_t sampleId);
    216     void addOneStssTableEntry(size_t sampleId);
    217 
    218     // Duration is time scale based
    219     void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
    220     void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
    221 
    222     bool isTrackMalFormed() const;
    223     void sendTrackSummary(bool hasMultipleTracks);
    224 
    225     // Write the boxes
    226     void writeStcoBox(bool use32BitOffset);
    227     void writeStscBox();
    228     void writeStszBox();
    229     void writeStssBox();
    230     void writeSttsBox();
    231     void writeCttsBox();
    232     void writeD263Box();
    233     void writePaspBox();
    234     void writeAvccBox();
    235     void writeUrlBox();
    236     void writeDrefBox();
    237     void writeDinfBox();
    238     void writeDamrBox();
    239     void writeMdhdBox(time_t now);
    240     void writeSmhdBox();
    241     void writeVmhdBox();
    242     void writeHdlrBox();
    243     void writeTkhdBox(time_t now);
    244     void writeMp4aEsdsBox();
    245     void writeMp4vEsdsBox();
    246     void writeAudioFourCCBox();
    247     void writeVideoFourCCBox();
    248     void writeStblBox(bool use32BitOffset);
    249 
    250     Track(const Track &);
    251     Track &operator=(const Track &);
    252 };
    253 
    254 MPEG4Writer::MPEG4Writer(const char *filename)
    255     : mFd(-1),
    256       mInitCheck(NO_INIT),
    257       mUse4ByteNalLength(true),
    258       mUse32BitOffset(true),
    259       mIsFileSizeLimitExplicitlyRequested(false),
    260       mPaused(false),
    261       mStarted(false),
    262       mWriterThreadStarted(false),
    263       mOffset(0),
    264       mMdatOffset(0),
    265       mEstimatedMoovBoxSize(0),
    266       mInterleaveDurationUs(1000000),
    267       mLatitudex10000(0),
    268       mLongitudex10000(0),
    269       mAreGeoTagsAvailable(false),
    270       mStartTimeOffsetMs(-1) {
    271 
    272     mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR);
    273     if (mFd >= 0) {
    274         mInitCheck = OK;
    275     }
    276 }
    277 
    278 MPEG4Writer::MPEG4Writer(int fd)
    279     : mFd(dup(fd)),
    280       mInitCheck(mFd < 0? NO_INIT: OK),
    281       mUse4ByteNalLength(true),
    282       mUse32BitOffset(true),
    283       mIsFileSizeLimitExplicitlyRequested(false),
    284       mPaused(false),
    285       mStarted(false),
    286       mWriterThreadStarted(false),
    287       mOffset(0),
    288       mMdatOffset(0),
    289       mEstimatedMoovBoxSize(0),
    290       mInterleaveDurationUs(1000000),
    291       mLatitudex10000(0),
    292       mLongitudex10000(0),
    293       mAreGeoTagsAvailable(false),
    294       mStartTimeOffsetMs(-1) {
    295 }
    296 
    297 MPEG4Writer::~MPEG4Writer() {
    298     reset();
    299 
    300     while (!mTracks.empty()) {
    301         List<Track *>::iterator it = mTracks.begin();
    302         delete *it;
    303         (*it) = NULL;
    304         mTracks.erase(it);
    305     }
    306     mTracks.clear();
    307 }
    308 
    309 status_t MPEG4Writer::dump(
    310         int fd, const Vector<String16>& args) {
    311     const size_t SIZE = 256;
    312     char buffer[SIZE];
    313     String8 result;
    314     snprintf(buffer, SIZE, "   MPEG4Writer %p\n", this);
    315     result.append(buffer);
    316     snprintf(buffer, SIZE, "     mStarted: %s\n", mStarted? "true": "false");
    317     result.append(buffer);
    318     ::write(fd, result.string(), result.size());
    319     for (List<Track *>::iterator it = mTracks.begin();
    320          it != mTracks.end(); ++it) {
    321         (*it)->dump(fd, args);
    322     }
    323     return OK;
    324 }
    325 
    326 status_t MPEG4Writer::Track::dump(
    327         int fd, const Vector<String16>& args) const {
    328     const size_t SIZE = 256;
    329     char buffer[SIZE];
    330     String8 result;
    331     snprintf(buffer, SIZE, "     %s track\n", mIsAudio? "Audio": "Video");
    332     result.append(buffer);
    333     snprintf(buffer, SIZE, "       reached EOS: %s\n",
    334             mReachedEOS? "true": "false");
    335     result.append(buffer);
    336     ::write(fd, result.string(), result.size());
    337     return OK;
    338 }
    339 
    340 status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
    341     Mutex::Autolock l(mLock);
    342     if (mStarted) {
    343         ALOGE("Attempt to add source AFTER recording is started");
    344         return UNKNOWN_ERROR;
    345     }
    346     Track *track = new Track(this, source, mTracks.size());
    347     mTracks.push_back(track);
    348 
    349     return OK;
    350 }
    351 
    352 status_t MPEG4Writer::startTracks(MetaData *params) {
    353     for (List<Track *>::iterator it = mTracks.begin();
    354          it != mTracks.end(); ++it) {
    355         status_t err = (*it)->start(params);
    356 
    357         if (err != OK) {
    358             for (List<Track *>::iterator it2 = mTracks.begin();
    359                  it2 != it; ++it2) {
    360                 (*it2)->stop();
    361             }
    362 
    363             return err;
    364         }
    365     }
    366     return OK;
    367 }
    368 
    369 int64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
    370     // This implementation is highly experimental/heurisitic.
    371     //
    372     // Statistical analysis shows that metadata usually accounts
    373     // for a small portion of the total file size, usually < 0.6%.
    374 
    375     // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
    376     // where 1MB is the common file size limit for MMS application.
    377     // The default MAX _MOOV_BOX_SIZE value is based on about 3
    378     // minute video recording with a bit rate about 3 Mbps, because
    379     // statistics also show that most of the video captured are going
    380     // to be less than 3 minutes.
    381 
    382     // If the estimation is wrong, we will pay the price of wasting
    383     // some reserved space. This should not happen so often statistically.
    384     static const int32_t factor = mUse32BitOffset? 1: 2;
    385     static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
    386     static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
    387     int64_t size = MIN_MOOV_BOX_SIZE;
    388 
    389     // Max file size limit is set
    390     if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
    391         size = mMaxFileSizeLimitBytes * 6 / 1000;
    392     }
    393 
    394     // Max file duration limit is set
    395     if (mMaxFileDurationLimitUs != 0) {
    396         if (bitRate > 0) {
    397             int64_t size2 =
    398                 ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
    399             if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
    400                 // When both file size and duration limits are set,
    401                 // we use the smaller limit of the two.
    402                 if (size > size2) {
    403                     size = size2;
    404                 }
    405             } else {
    406                 // Only max file duration limit is set
    407                 size = size2;
    408             }
    409         }
    410     }
    411 
    412     if (size < MIN_MOOV_BOX_SIZE) {
    413         size = MIN_MOOV_BOX_SIZE;
    414     }
    415 
    416     // Any long duration recording will be probably end up with
    417     // non-streamable mp4 file.
    418     if (size > MAX_MOOV_BOX_SIZE) {
    419         size = MAX_MOOV_BOX_SIZE;
    420     }
    421 
    422     ALOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
    423          " moov size %lld bytes",
    424          mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
    425     return factor * size;
    426 }
    427 
    428 status_t MPEG4Writer::start(MetaData *param) {
    429     if (mInitCheck != OK) {
    430         return UNKNOWN_ERROR;
    431     }
    432 
    433     /*
    434      * Check mMaxFileSizeLimitBytes at the beginning
    435      * since mMaxFileSizeLimitBytes may be implicitly
    436      * changed later for 32-bit file offset even if
    437      * user does not ask to set it explicitly.
    438      */
    439     if (mMaxFileSizeLimitBytes != 0) {
    440         mIsFileSizeLimitExplicitlyRequested = true;
    441     }
    442 
    443     int32_t use64BitOffset;
    444     if (param &&
    445         param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
    446         use64BitOffset) {
    447         mUse32BitOffset = false;
    448     }
    449 
    450     if (mUse32BitOffset) {
    451         // Implicit 32 bit file size limit
    452         if (mMaxFileSizeLimitBytes == 0) {
    453             mMaxFileSizeLimitBytes = kMax32BitFileSize;
    454         }
    455 
    456         // If file size is set to be larger than the 32 bit file
    457         // size limit, treat it as an error.
    458         if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
    459             ALOGW("32-bit file size limit (%lld bytes) too big. "
    460                  "It is changed to %lld bytes",
    461                 mMaxFileSizeLimitBytes, kMax32BitFileSize);
    462             mMaxFileSizeLimitBytes = kMax32BitFileSize;
    463         }
    464     }
    465 
    466     int32_t use2ByteNalLength;
    467     if (param &&
    468         param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
    469         use2ByteNalLength) {
    470         mUse4ByteNalLength = false;
    471     }
    472 
    473     mStartTimestampUs = -1;
    474 
    475     if (mStarted) {
    476         if (mPaused) {
    477             mPaused = false;
    478             return startTracks(param);
    479         }
    480         return OK;
    481     }
    482 
    483     if (!param ||
    484         !param->findInt32(kKeyTimeScale, &mTimeScale)) {
    485         mTimeScale = 1000;
    486     }
    487     CHECK_GT(mTimeScale, 0);
    488     ALOGV("movie time scale: %d", mTimeScale);
    489 
    490     mStreamableFile = true;
    491     mWriteMoovBoxToMemory = false;
    492     mMoovBoxBuffer = NULL;
    493     mMoovBoxBufferOffset = 0;
    494 
    495     writeFtypBox(param);
    496 
    497     mFreeBoxOffset = mOffset;
    498 
    499     if (mEstimatedMoovBoxSize == 0) {
    500         int32_t bitRate = -1;
    501         if (param) {
    502             param->findInt32(kKeyBitRate, &bitRate);
    503         }
    504         mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
    505     }
    506     CHECK_GE(mEstimatedMoovBoxSize, 8);
    507     lseek64(mFd, mFreeBoxOffset, SEEK_SET);
    508     writeInt32(mEstimatedMoovBoxSize);
    509     write("free", 4);
    510 
    511     mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
    512     mOffset = mMdatOffset;
    513     lseek64(mFd, mMdatOffset, SEEK_SET);
    514     if (mUse32BitOffset) {
    515         write("????mdat", 8);
    516     } else {
    517         write("\x00\x00\x00\x01mdat????????", 16);
    518     }
    519 
    520     status_t err = startWriterThread();
    521     if (err != OK) {
    522         return err;
    523     }
    524 
    525     err = startTracks(param);
    526     if (err != OK) {
    527         return err;
    528     }
    529 
    530     mStarted = true;
    531     return OK;
    532 }
    533 
    534 bool MPEG4Writer::use32BitFileOffset() const {
    535     return mUse32BitOffset;
    536 }
    537 
    538 status_t MPEG4Writer::pause() {
    539     if (mInitCheck != OK) {
    540         return OK;
    541     }
    542     mPaused = true;
    543     status_t err = OK;
    544     for (List<Track *>::iterator it = mTracks.begin();
    545          it != mTracks.end(); ++it) {
    546         status_t status = (*it)->pause();
    547         if (status != OK) {
    548             err = status;
    549         }
    550     }
    551     return err;
    552 }
    553 
    554 void MPEG4Writer::stopWriterThread() {
    555     ALOGD("Stopping writer thread");
    556     if (!mWriterThreadStarted) {
    557         return;
    558     }
    559 
    560     {
    561         Mutex::Autolock autolock(mLock);
    562 
    563         mDone = true;
    564         mChunkReadyCondition.signal();
    565     }
    566 
    567     void *dummy;
    568     pthread_join(mThread, &dummy);
    569     mWriterThreadStarted = false;
    570     ALOGD("Writer thread stopped");
    571 }
    572 
    573 /*
    574  * MP4 file standard defines a composition matrix:
    575  * | a  b  u |
    576  * | c  d  v |
    577  * | x  y  w |
    578  *
    579  * the element in the matrix is stored in the following
    580  * order: {a, b, u, c, d, v, x, y, w},
    581  * where a, b, c, d, x, and y is in 16.16 format, while
    582  * u, v and w is in 2.30 format.
    583  */
    584 void MPEG4Writer::writeCompositionMatrix(int degrees) {
    585     ALOGV("writeCompositionMatrix");
    586     uint32_t a = 0x00010000;
    587     uint32_t b = 0;
    588     uint32_t c = 0;
    589     uint32_t d = 0x00010000;
    590     switch (degrees) {
    591         case 0:
    592             break;
    593         case 90:
    594             a = 0;
    595             b = 0x00010000;
    596             c = 0xFFFF0000;
    597             d = 0;
    598             break;
    599         case 180:
    600             a = 0xFFFF0000;
    601             d = 0xFFFF0000;
    602             break;
    603         case 270:
    604             a = 0;
    605             b = 0xFFFF0000;
    606             c = 0x00010000;
    607             d = 0;
    608             break;
    609         default:
    610             CHECK(!"Should never reach this unknown rotation");
    611             break;
    612     }
    613 
    614     writeInt32(a);           // a
    615     writeInt32(b);           // b
    616     writeInt32(0);           // u
    617     writeInt32(c);           // c
    618     writeInt32(d);           // d
    619     writeInt32(0);           // v
    620     writeInt32(0);           // x
    621     writeInt32(0);           // y
    622     writeInt32(0x40000000);  // w
    623 }
    624 
    625 void MPEG4Writer::release() {
    626     close(mFd);
    627     mFd = -1;
    628     mInitCheck = NO_INIT;
    629     mStarted = false;
    630 }
    631 
    632 status_t MPEG4Writer::reset() {
    633     if (mInitCheck != OK) {
    634         return OK;
    635     } else {
    636         if (!mWriterThreadStarted ||
    637             !mStarted) {
    638             if (mWriterThreadStarted) {
    639                 stopWriterThread();
    640             }
    641             release();
    642             return OK;
    643         }
    644     }
    645 
    646     status_t err = OK;
    647     int64_t maxDurationUs = 0;
    648     int64_t minDurationUs = 0x7fffffffffffffffLL;
    649     for (List<Track *>::iterator it = mTracks.begin();
    650          it != mTracks.end(); ++it) {
    651         status_t status = (*it)->stop();
    652         if (err == OK && status != OK) {
    653             err = status;
    654         }
    655 
    656         int64_t durationUs = (*it)->getDurationUs();
    657         if (durationUs > maxDurationUs) {
    658             maxDurationUs = durationUs;
    659         }
    660         if (durationUs < minDurationUs) {
    661             minDurationUs = durationUs;
    662         }
    663     }
    664 
    665     if (mTracks.size() > 1) {
    666         ALOGD("Duration from tracks range is [%lld, %lld] us",
    667             minDurationUs, maxDurationUs);
    668     }
    669 
    670     stopWriterThread();
    671 
    672     // Do not write out movie header on error.
    673     if (err != OK) {
    674         release();
    675         return err;
    676     }
    677 
    678     // Fix up the size of the 'mdat' chunk.
    679     if (mUse32BitOffset) {
    680         lseek64(mFd, mMdatOffset, SEEK_SET);
    681         int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
    682         ::write(mFd, &size, 4);
    683     } else {
    684         lseek64(mFd, mMdatOffset + 8, SEEK_SET);
    685         int64_t size = mOffset - mMdatOffset;
    686         size = hton64(size);
    687         ::write(mFd, &size, 8);
    688     }
    689     lseek64(mFd, mOffset, SEEK_SET);
    690 
    691     const off64_t moovOffset = mOffset;
    692     mWriteMoovBoxToMemory = true;
    693     mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
    694     mMoovBoxBufferOffset = 0;
    695     CHECK(mMoovBoxBuffer != NULL);
    696     writeMoovBox(maxDurationUs);
    697 
    698     mWriteMoovBoxToMemory = false;
    699     if (mStreamableFile) {
    700         CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
    701 
    702         // Moov box
    703         lseek64(mFd, mFreeBoxOffset, SEEK_SET);
    704         mOffset = mFreeBoxOffset;
    705         write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
    706 
    707         // Free box
    708         lseek64(mFd, mOffset, SEEK_SET);
    709         writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
    710         write("free", 4);
    711 
    712         // Free temp memory
    713         free(mMoovBoxBuffer);
    714         mMoovBoxBuffer = NULL;
    715         mMoovBoxBufferOffset = 0;
    716     } else {
    717         ALOGI("The mp4 file will not be streamable.");
    718     }
    719 
    720     CHECK(mBoxes.empty());
    721 
    722     release();
    723     return err;
    724 }
    725 
    726 void MPEG4Writer::writeMvhdBox(int64_t durationUs) {
    727     time_t now = time(NULL);
    728     beginBox("mvhd");
    729     writeInt32(0);             // version=0, flags=0
    730     writeInt32(now);           // creation time
    731     writeInt32(now);           // modification time
    732     writeInt32(mTimeScale);    // mvhd timescale
    733     int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
    734     writeInt32(duration);
    735     writeInt32(0x10000);       // rate: 1.0
    736     writeInt16(0x100);         // volume
    737     writeInt16(0);             // reserved
    738     writeInt32(0);             // reserved
    739     writeInt32(0);             // reserved
    740     writeCompositionMatrix(0); // matrix
    741     writeInt32(0);             // predefined
    742     writeInt32(0);             // predefined
    743     writeInt32(0);             // predefined
    744     writeInt32(0);             // predefined
    745     writeInt32(0);             // predefined
    746     writeInt32(0);             // predefined
    747     writeInt32(mTracks.size() + 1);  // nextTrackID
    748     endBox();  // mvhd
    749 }
    750 
    751 void MPEG4Writer::writeMoovBox(int64_t durationUs) {
    752     beginBox("moov");
    753     writeMvhdBox(durationUs);
    754     if (mAreGeoTagsAvailable) {
    755         writeUdtaBox();
    756     }
    757     int32_t id = 1;
    758     for (List<Track *>::iterator it = mTracks.begin();
    759         it != mTracks.end(); ++it, ++id) {
    760         (*it)->writeTrackHeader(mUse32BitOffset);
    761     }
    762     endBox();  // moov
    763 }
    764 
    765 void MPEG4Writer::writeFtypBox(MetaData *param) {
    766     beginBox("ftyp");
    767 
    768     int32_t fileType;
    769     if (param && param->findInt32(kKeyFileType, &fileType) &&
    770         fileType != OUTPUT_FORMAT_MPEG_4) {
    771         writeFourcc("3gp4");
    772     } else {
    773         writeFourcc("isom");
    774     }
    775 
    776     writeInt32(0);
    777     writeFourcc("isom");
    778     writeFourcc("3gp4");
    779     endBox();
    780 }
    781 
    782 static bool isTestModeEnabled() {
    783 #if (PROPERTY_VALUE_MAX < 5)
    784 #error "PROPERTY_VALUE_MAX must be at least 5"
    785 #endif
    786 
    787     // Test mode is enabled only if rw.media.record.test system
    788     // property is enabled.
    789     char value[PROPERTY_VALUE_MAX];
    790     if (property_get("rw.media.record.test", value, NULL) &&
    791         (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
    792         return true;
    793     }
    794     return false;
    795 }
    796 
    797 void MPEG4Writer::sendSessionSummary() {
    798     // Send session summary only if test mode is enabled
    799     if (!isTestModeEnabled()) {
    800         return;
    801     }
    802 
    803     for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
    804          it != mChunkInfos.end(); ++it) {
    805         int trackNum = it->mTrack->getTrackId() << 28;
    806         notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
    807                 trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
    808                 it->mMaxInterChunkDurUs);
    809     }
    810 }
    811 
    812 status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
    813     mInterleaveDurationUs = durationUs;
    814     return OK;
    815 }
    816 
    817 void MPEG4Writer::lock() {
    818     mLock.lock();
    819 }
    820 
    821 void MPEG4Writer::unlock() {
    822     mLock.unlock();
    823 }
    824 
    825 off64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
    826     off64_t old_offset = mOffset;
    827 
    828     ::write(mFd,
    829           (const uint8_t *)buffer->data() + buffer->range_offset(),
    830           buffer->range_length());
    831 
    832     mOffset += buffer->range_length();
    833 
    834     return old_offset;
    835 }
    836 
    837 static void StripStartcode(MediaBuffer *buffer) {
    838     if (buffer->range_length() < 4) {
    839         return;
    840     }
    841 
    842     const uint8_t *ptr =
    843         (const uint8_t *)buffer->data() + buffer->range_offset();
    844 
    845     if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
    846         buffer->set_range(
    847                 buffer->range_offset() + 4, buffer->range_length() - 4);
    848     }
    849 }
    850 
    851 off64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
    852     off64_t old_offset = mOffset;
    853 
    854     size_t length = buffer->range_length();
    855 
    856     if (mUse4ByteNalLength) {
    857         uint8_t x = length >> 24;
    858         ::write(mFd, &x, 1);
    859         x = (length >> 16) & 0xff;
    860         ::write(mFd, &x, 1);
    861         x = (length >> 8) & 0xff;
    862         ::write(mFd, &x, 1);
    863         x = length & 0xff;
    864         ::write(mFd, &x, 1);
    865 
    866         ::write(mFd,
    867               (const uint8_t *)buffer->data() + buffer->range_offset(),
    868               length);
    869 
    870         mOffset += length + 4;
    871     } else {
    872         CHECK_LT(length, 65536);
    873 
    874         uint8_t x = length >> 8;
    875         ::write(mFd, &x, 1);
    876         x = length & 0xff;
    877         ::write(mFd, &x, 1);
    878         ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
    879         mOffset += length + 2;
    880     }
    881 
    882     return old_offset;
    883 }
    884 
    885 size_t MPEG4Writer::write(
    886         const void *ptr, size_t size, size_t nmemb) {
    887 
    888     const size_t bytes = size * nmemb;
    889     if (mWriteMoovBoxToMemory) {
    890         // This happens only when we write the moov box at the end of
    891         // recording, not for each output video/audio frame we receive.
    892         off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
    893         if (moovBoxSize > mEstimatedMoovBoxSize) {
    894             for (List<off64_t>::iterator it = mBoxes.begin();
    895                  it != mBoxes.end(); ++it) {
    896                 (*it) += mOffset;
    897             }
    898             lseek64(mFd, mOffset, SEEK_SET);
    899             ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
    900             ::write(mFd, ptr, size * nmemb);
    901             mOffset += (bytes + mMoovBoxBufferOffset);
    902             free(mMoovBoxBuffer);
    903             mMoovBoxBuffer = NULL;
    904             mMoovBoxBufferOffset = 0;
    905             mWriteMoovBoxToMemory = false;
    906             mStreamableFile = false;
    907         } else {
    908             memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
    909             mMoovBoxBufferOffset += bytes;
    910         }
    911     } else {
    912         ::write(mFd, ptr, size * nmemb);
    913         mOffset += bytes;
    914     }
    915     return bytes;
    916 }
    917 
    918 void MPEG4Writer::beginBox(const char *fourcc) {
    919     CHECK_EQ(strlen(fourcc), 4);
    920 
    921     mBoxes.push_back(mWriteMoovBoxToMemory?
    922             mMoovBoxBufferOffset: mOffset);
    923 
    924     writeInt32(0);
    925     writeFourcc(fourcc);
    926 }
    927 
    928 void MPEG4Writer::endBox() {
    929     CHECK(!mBoxes.empty());
    930 
    931     off64_t offset = *--mBoxes.end();
    932     mBoxes.erase(--mBoxes.end());
    933 
    934     if (mWriteMoovBoxToMemory) {
    935        int32_t x = htonl(mMoovBoxBufferOffset - offset);
    936        memcpy(mMoovBoxBuffer + offset, &x, 4);
    937     } else {
    938         lseek64(mFd, offset, SEEK_SET);
    939         writeInt32(mOffset - offset);
    940         mOffset -= 4;
    941         lseek64(mFd, mOffset, SEEK_SET);
    942     }
    943 }
    944 
    945 void MPEG4Writer::writeInt8(int8_t x) {
    946     write(&x, 1, 1);
    947 }
    948 
    949 void MPEG4Writer::writeInt16(int16_t x) {
    950     x = htons(x);
    951     write(&x, 1, 2);
    952 }
    953 
    954 void MPEG4Writer::writeInt32(int32_t x) {
    955     x = htonl(x);
    956     write(&x, 1, 4);
    957 }
    958 
    959 void MPEG4Writer::writeInt64(int64_t x) {
    960     x = hton64(x);
    961     write(&x, 1, 8);
    962 }
    963 
    964 void MPEG4Writer::writeCString(const char *s) {
    965     size_t n = strlen(s);
    966     write(s, 1, n + 1);
    967 }
    968 
    969 void MPEG4Writer::writeFourcc(const char *s) {
    970     CHECK_EQ(strlen(s), 4);
    971     write(s, 1, 4);
    972 }
    973 
    974 
    975 // Written in +/-DD.DDDD format
    976 void MPEG4Writer::writeLatitude(int degreex10000) {
    977     bool isNegative = (degreex10000 < 0);
    978     char sign = isNegative? '-': '+';
    979 
    980     // Handle the whole part
    981     char str[9];
    982     int wholePart = degreex10000 / 10000;
    983     if (wholePart == 0) {
    984         snprintf(str, 5, "%c%.2d.", sign, wholePart);
    985     } else {
    986         snprintf(str, 5, "%+.2d.", wholePart);
    987     }
    988 
    989     // Handle the fractional part
    990     int fractionalPart = degreex10000 - (wholePart * 10000);
    991     if (fractionalPart < 0) {
    992         fractionalPart = -fractionalPart;
    993     }
    994     snprintf(&str[4], 5, "%.4d", fractionalPart);
    995 
    996     // Do not write the null terminator
    997     write(str, 1, 8);
    998 }
    999 
   1000 // Written in +/- DDD.DDDD format
   1001 void MPEG4Writer::writeLongitude(int degreex10000) {
   1002     bool isNegative = (degreex10000 < 0);
   1003     char sign = isNegative? '-': '+';
   1004 
   1005     // Handle the whole part
   1006     char str[10];
   1007     int wholePart = degreex10000 / 10000;
   1008     if (wholePart == 0) {
   1009         snprintf(str, 6, "%c%.3d.", sign, wholePart);
   1010     } else {
   1011         snprintf(str, 6, "%+.3d.", wholePart);
   1012     }
   1013 
   1014     // Handle the fractional part
   1015     int fractionalPart = degreex10000 - (wholePart * 10000);
   1016     if (fractionalPart < 0) {
   1017         fractionalPart = -fractionalPart;
   1018     }
   1019     snprintf(&str[5], 5, "%.4d", fractionalPart);
   1020 
   1021     // Do not write the null terminator
   1022     write(str, 1, 9);
   1023 }
   1024 
   1025 /*
   1026  * Geodata is stored according to ISO-6709 standard.
   1027  * latitudex10000 is latitude in degrees times 10000, and
   1028  * longitudex10000 is longitude in degrees times 10000.
   1029  * The range for the latitude is in [-90, +90], and
   1030  * The range for the longitude is in [-180, +180]
   1031  */
   1032 status_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
   1033     // Is latitude or longitude out of range?
   1034     if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
   1035         longitudex10000 < -1800000 || longitudex10000 > 1800000) {
   1036         return BAD_VALUE;
   1037     }
   1038 
   1039     mLatitudex10000 = latitudex10000;
   1040     mLongitudex10000 = longitudex10000;
   1041     mAreGeoTagsAvailable = true;
   1042     return OK;
   1043 }
   1044 
   1045 void MPEG4Writer::write(const void *data, size_t size) {
   1046     write(data, 1, size);
   1047 }
   1048 
   1049 bool MPEG4Writer::isFileStreamable() const {
   1050     return mStreamableFile;
   1051 }
   1052 
   1053 bool MPEG4Writer::exceedsFileSizeLimit() {
   1054     // No limit
   1055     if (mMaxFileSizeLimitBytes == 0) {
   1056         return false;
   1057     }
   1058 
   1059     int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
   1060     for (List<Track *>::iterator it = mTracks.begin();
   1061          it != mTracks.end(); ++it) {
   1062         nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
   1063     }
   1064 
   1065     // Be conservative in the estimate: do not exceed 95% of
   1066     // the target file limit. For small target file size limit, though,
   1067     // this will not help.
   1068     return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
   1069 }
   1070 
   1071 bool MPEG4Writer::exceedsFileDurationLimit() {
   1072     // No limit
   1073     if (mMaxFileDurationLimitUs == 0) {
   1074         return false;
   1075     }
   1076 
   1077     for (List<Track *>::iterator it = mTracks.begin();
   1078          it != mTracks.end(); ++it) {
   1079         if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
   1080             return true;
   1081         }
   1082     }
   1083     return false;
   1084 }
   1085 
   1086 bool MPEG4Writer::reachedEOS() {
   1087     bool allDone = true;
   1088     for (List<Track *>::iterator it = mTracks.begin();
   1089          it != mTracks.end(); ++it) {
   1090         if (!(*it)->reachedEOS()) {
   1091             allDone = false;
   1092             break;
   1093         }
   1094     }
   1095 
   1096     return allDone;
   1097 }
   1098 
   1099 void MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
   1100     ALOGI("setStartTimestampUs: %lld", timeUs);
   1101     CHECK_GE(timeUs, 0ll);
   1102     Mutex::Autolock autoLock(mLock);
   1103     if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
   1104         mStartTimestampUs = timeUs;
   1105         ALOGI("Earliest track starting time: %lld", mStartTimestampUs);
   1106     }
   1107 }
   1108 
   1109 int64_t MPEG4Writer::getStartTimestampUs() {
   1110     Mutex::Autolock autoLock(mLock);
   1111     return mStartTimestampUs;
   1112 }
   1113 
   1114 size_t MPEG4Writer::numTracks() {
   1115     Mutex::Autolock autolock(mLock);
   1116     return mTracks.size();
   1117 }
   1118 
   1119 ////////////////////////////////////////////////////////////////////////////////
   1120 
   1121 MPEG4Writer::Track::Track(
   1122         MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
   1123     : mOwner(owner),
   1124       mMeta(source->getFormat()),
   1125       mSource(source),
   1126       mDone(false),
   1127       mPaused(false),
   1128       mResumed(false),
   1129       mStarted(false),
   1130       mTrackId(trackId),
   1131       mTrackDurationUs(0),
   1132       mEstimatedTrackSizeBytes(0),
   1133       mSamplesHaveSameSize(true),
   1134       mCodecSpecificData(NULL),
   1135       mCodecSpecificDataSize(0),
   1136       mGotAllCodecSpecificData(false),
   1137       mReachedEOS(false),
   1138       mRotation(0) {
   1139     getCodecSpecificDataFromInputFormatIfPossible();
   1140 
   1141     const char *mime;
   1142     mMeta->findCString(kKeyMIMEType, &mime);
   1143     mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
   1144     mIsAudio = !strncasecmp(mime, "audio/", 6);
   1145     mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
   1146                !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
   1147 
   1148     setTimeScale();
   1149 }
   1150 
   1151 void MPEG4Writer::Track::updateTrackSizeEstimate() {
   1152 
   1153     int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset()
   1154                                 ? mNumStcoTableEntries * 4
   1155                                 : mNumStcoTableEntries * 8;
   1156 
   1157     int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4);
   1158 
   1159     mEstimatedTrackSizeBytes = mMdatSizeBytes;  // media data size
   1160     if (!mOwner->isFileStreamable()) {
   1161         // Reserved free space is not large enough to hold
   1162         // all meta data and thus wasted.
   1163         mEstimatedTrackSizeBytes += mNumStscTableEntries * 12 +  // stsc box size
   1164                                     mNumStssTableEntries * 4 +   // stss box size
   1165                                     mNumSttsTableEntries * 8 +   // stts box size
   1166                                     mNumCttsTableEntries * 8 +   // ctts box size
   1167                                     stcoBoxSizeBytes +           // stco box size
   1168                                     stszBoxSizeBytes;            // stsz box size
   1169     }
   1170 }
   1171 
   1172 void MPEG4Writer::Track::addOneStscTableEntry(
   1173         size_t chunkId, size_t sampleId) {
   1174 
   1175         StscTableEntry stscEntry(chunkId, sampleId, 1);
   1176         mStscTableEntries.push_back(stscEntry);
   1177         ++mNumStscTableEntries;
   1178 }
   1179 
   1180 void MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
   1181     mStssTableEntries.push_back(sampleId);
   1182     ++mNumStssTableEntries;
   1183 }
   1184 
   1185 void MPEG4Writer::Track::addOneSttsTableEntry(
   1186         size_t sampleCount, int32_t duration) {
   1187 
   1188     if (duration == 0) {
   1189         ALOGW("0-duration samples found: %d", sampleCount);
   1190     }
   1191     SttsTableEntry sttsEntry(sampleCount, duration);
   1192     mSttsTableEntries.push_back(sttsEntry);
   1193     ++mNumSttsTableEntries;
   1194 }
   1195 
   1196 void MPEG4Writer::Track::addOneCttsTableEntry(
   1197         size_t sampleCount, int32_t duration) {
   1198 
   1199     if (mIsAudio) {
   1200         return;
   1201     }
   1202     CttsTableEntry cttsEntry(sampleCount, duration);
   1203     mCttsTableEntries.push_back(cttsEntry);
   1204     ++mNumCttsTableEntries;
   1205 }
   1206 
   1207 void MPEG4Writer::Track::addChunkOffset(off64_t offset) {
   1208     ++mNumStcoTableEntries;
   1209     mChunkOffsets.push_back(offset);
   1210 }
   1211 
   1212 void MPEG4Writer::Track::setTimeScale() {
   1213     ALOGV("setTimeScale");
   1214     // Default time scale
   1215     mTimeScale = 90000;
   1216 
   1217     if (mIsAudio) {
   1218         // Use the sampling rate as the default time scale for audio track.
   1219         int32_t sampleRate;
   1220         bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
   1221         CHECK(success);
   1222         mTimeScale = sampleRate;
   1223     }
   1224 
   1225     // If someone would like to overwrite the timescale, use user-supplied value.
   1226     int32_t timeScale;
   1227     if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
   1228         mTimeScale = timeScale;
   1229     }
   1230 
   1231     CHECK_GT(mTimeScale, 0);
   1232 }
   1233 
   1234 void MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
   1235     const char *mime;
   1236     CHECK(mMeta->findCString(kKeyMIMEType, &mime));
   1237 
   1238     if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
   1239         uint32_t type;
   1240         const void *data;
   1241         size_t size;
   1242         if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
   1243             mCodecSpecificData = malloc(size);
   1244             mCodecSpecificDataSize = size;
   1245             memcpy(mCodecSpecificData, data, size);
   1246             mGotAllCodecSpecificData = true;
   1247         }
   1248     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
   1249             || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
   1250         uint32_t type;
   1251         const void *data;
   1252         size_t size;
   1253         if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
   1254             ESDS esds(data, size);
   1255             if (esds.getCodecSpecificInfo(&data, &size) == OK) {
   1256                 mCodecSpecificData = malloc(size);
   1257                 mCodecSpecificDataSize = size;
   1258                 memcpy(mCodecSpecificData, data, size);
   1259                 mGotAllCodecSpecificData = true;
   1260             }
   1261         }
   1262     }
   1263 }
   1264 
   1265 MPEG4Writer::Track::~Track() {
   1266     stop();
   1267 
   1268     if (mCodecSpecificData != NULL) {
   1269         free(mCodecSpecificData);
   1270         mCodecSpecificData = NULL;
   1271     }
   1272 
   1273     while (!mSampleSizes.empty()) {
   1274         List<uint32_t *>::iterator it = mSampleSizes.begin();
   1275         delete[] (*it);
   1276         mSampleSizes.erase(it);
   1277     }
   1278 }
   1279 
   1280 void MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
   1281     ALOGV("initTrackingProgressStatus");
   1282     mPreviousTrackTimeUs = -1;
   1283     mTrackingProgressStatus = false;
   1284     mTrackEveryTimeDurationUs = 0;
   1285     {
   1286         int64_t timeUs;
   1287         if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
   1288             ALOGV("Receive request to track progress status for every %lld us", timeUs);
   1289             mTrackEveryTimeDurationUs = timeUs;
   1290             mTrackingProgressStatus = true;
   1291         }
   1292     }
   1293 }
   1294 
   1295 // static
   1296 void *MPEG4Writer::ThreadWrapper(void *me) {
   1297     ALOGV("ThreadWrapper: %p", me);
   1298     MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
   1299     writer->threadFunc();
   1300     return NULL;
   1301 }
   1302 
   1303 void MPEG4Writer::bufferChunk(const Chunk& chunk) {
   1304     ALOGV("bufferChunk: %p", chunk.mTrack);
   1305     Mutex::Autolock autolock(mLock);
   1306     CHECK_EQ(mDone, false);
   1307 
   1308     for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
   1309          it != mChunkInfos.end(); ++it) {
   1310 
   1311         if (chunk.mTrack == it->mTrack) {  // Found owner
   1312             it->mChunks.push_back(chunk);
   1313             mChunkReadyCondition.signal();
   1314             return;
   1315         }
   1316     }
   1317 
   1318     CHECK(!"Received a chunk for a unknown track");
   1319 }
   1320 
   1321 void MPEG4Writer::writeChunkToFile(Chunk* chunk) {
   1322     ALOGV("writeChunkToFile: %lld from %s track",
   1323         chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video");
   1324 
   1325     int32_t isFirstSample = true;
   1326     while (!chunk->mSamples.empty()) {
   1327         List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
   1328 
   1329         off64_t offset = chunk->mTrack->isAvc()
   1330                                 ? addLengthPrefixedSample_l(*it)
   1331                                 : addSample_l(*it);
   1332 
   1333         if (isFirstSample) {
   1334             chunk->mTrack->addChunkOffset(offset);
   1335             isFirstSample = false;
   1336         }
   1337 
   1338         (*it)->release();
   1339         (*it) = NULL;
   1340         chunk->mSamples.erase(it);
   1341     }
   1342     chunk->mSamples.clear();
   1343 }
   1344 
   1345 void MPEG4Writer::writeAllChunks() {
   1346     ALOGV("writeAllChunks");
   1347     size_t outstandingChunks = 0;
   1348     Chunk chunk;
   1349     while (findChunkToWrite(&chunk)) {
   1350         writeChunkToFile(&chunk);
   1351         ++outstandingChunks;
   1352     }
   1353 
   1354     sendSessionSummary();
   1355 
   1356     mChunkInfos.clear();
   1357     ALOGD("%d chunks are written in the last batch", outstandingChunks);
   1358 }
   1359 
   1360 bool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
   1361     ALOGV("findChunkToWrite");
   1362 
   1363     int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
   1364     Track *track = NULL;
   1365     for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
   1366          it != mChunkInfos.end(); ++it) {
   1367         if (!it->mChunks.empty()) {
   1368             List<Chunk>::iterator chunkIt = it->mChunks.begin();
   1369             if (chunkIt->mTimeStampUs < minTimestampUs) {
   1370                 minTimestampUs = chunkIt->mTimeStampUs;
   1371                 track = it->mTrack;
   1372             }
   1373         }
   1374     }
   1375 
   1376     if (track == NULL) {
   1377         ALOGV("Nothing to be written after all");
   1378         return false;
   1379     }
   1380 
   1381     if (mIsFirstChunk) {
   1382         mIsFirstChunk = false;
   1383     }
   1384 
   1385     for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
   1386          it != mChunkInfos.end(); ++it) {
   1387         if (it->mTrack == track) {
   1388             *chunk = *(it->mChunks.begin());
   1389             it->mChunks.erase(it->mChunks.begin());
   1390             CHECK_EQ(chunk->mTrack, track);
   1391 
   1392             int64_t interChunkTimeUs =
   1393                 chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
   1394             if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
   1395                 it->mMaxInterChunkDurUs = interChunkTimeUs;
   1396             }
   1397 
   1398             return true;
   1399         }
   1400     }
   1401 
   1402     return false;
   1403 }
   1404 
   1405 void MPEG4Writer::threadFunc() {
   1406     ALOGV("threadFunc");
   1407 
   1408     prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
   1409 
   1410     Mutex::Autolock autoLock(mLock);
   1411     while (!mDone) {
   1412         Chunk chunk;
   1413         bool chunkFound = false;
   1414 
   1415         while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
   1416             mChunkReadyCondition.wait(mLock);
   1417         }
   1418 
   1419         // Actual write without holding the lock in order to
   1420         // reduce the blocking time for media track threads.
   1421         if (chunkFound) {
   1422             mLock.unlock();
   1423             writeChunkToFile(&chunk);
   1424             mLock.lock();
   1425         }
   1426     }
   1427 
   1428     writeAllChunks();
   1429 }
   1430 
   1431 status_t MPEG4Writer::startWriterThread() {
   1432     ALOGV("startWriterThread");
   1433 
   1434     mDone = false;
   1435     mIsFirstChunk = true;
   1436     mDriftTimeUs = 0;
   1437     for (List<Track *>::iterator it = mTracks.begin();
   1438          it != mTracks.end(); ++it) {
   1439         ChunkInfo info;
   1440         info.mTrack = *it;
   1441         info.mPrevChunkTimestampUs = 0;
   1442         info.mMaxInterChunkDurUs = 0;
   1443         mChunkInfos.push_back(info);
   1444     }
   1445 
   1446     pthread_attr_t attr;
   1447     pthread_attr_init(&attr);
   1448     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
   1449     pthread_create(&mThread, &attr, ThreadWrapper, this);
   1450     pthread_attr_destroy(&attr);
   1451     mWriterThreadStarted = true;
   1452     return OK;
   1453 }
   1454 
   1455 
   1456 status_t MPEG4Writer::Track::start(MetaData *params) {
   1457     if (!mDone && mPaused) {
   1458         mPaused = false;
   1459         mResumed = true;
   1460         return OK;
   1461     }
   1462 
   1463     int64_t startTimeUs;
   1464     if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
   1465         startTimeUs = 0;
   1466     }
   1467     mStartTimeRealUs = startTimeUs;
   1468 
   1469     int32_t rotationDegrees;
   1470     if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
   1471         mRotation = rotationDegrees;
   1472     }
   1473 
   1474     mIsRealTimeRecording = true;
   1475     {
   1476         int32_t isNotRealTime;
   1477         if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
   1478             mIsRealTimeRecording = (isNotRealTime == 0);
   1479         }
   1480     }
   1481 
   1482     initTrackingProgressStatus(params);
   1483 
   1484     sp<MetaData> meta = new MetaData;
   1485     if (mIsRealTimeRecording && mOwner->numTracks() > 1) {
   1486         /*
   1487          * This extra delay of accepting incoming audio/video signals
   1488          * helps to align a/v start time at the beginning of a recording
   1489          * session, and it also helps eliminate the "recording" sound for
   1490          * camcorder applications.
   1491          *
   1492          * If client does not set the start time offset, we fall back to
   1493          * use the default initial delay value.
   1494          */
   1495         int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
   1496         if (startTimeOffsetUs < 0) {  // Start time offset was not set
   1497             startTimeOffsetUs = kInitialDelayTimeUs;
   1498         }
   1499         startTimeUs += startTimeOffsetUs;
   1500         ALOGI("Start time offset: %lld us", startTimeOffsetUs);
   1501     }
   1502 
   1503     meta->setInt64(kKeyTime, startTimeUs);
   1504 
   1505     status_t err = mSource->start(meta.get());
   1506     if (err != OK) {
   1507         mDone = mReachedEOS = true;
   1508         return err;
   1509     }
   1510 
   1511     pthread_attr_t attr;
   1512     pthread_attr_init(&attr);
   1513     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
   1514 
   1515     mDone = false;
   1516     mStarted = true;
   1517     mTrackDurationUs = 0;
   1518     mReachedEOS = false;
   1519     mEstimatedTrackSizeBytes = 0;
   1520     mNumStcoTableEntries = 0;
   1521     mNumStssTableEntries = 0;
   1522     mNumStscTableEntries = 0;
   1523     mNumSttsTableEntries = 0;
   1524     mNumCttsTableEntries = 0;
   1525     mMdatSizeBytes = 0;
   1526 
   1527     mMaxChunkDurationUs = 0;
   1528 
   1529     pthread_create(&mThread, &attr, ThreadWrapper, this);
   1530     pthread_attr_destroy(&attr);
   1531 
   1532     return OK;
   1533 }
   1534 
   1535 status_t MPEG4Writer::Track::pause() {
   1536     mPaused = true;
   1537     return OK;
   1538 }
   1539 
   1540 status_t MPEG4Writer::Track::stop() {
   1541     ALOGD("Stopping %s track", mIsAudio? "Audio": "Video");
   1542     if (!mStarted) {
   1543         ALOGE("Stop() called but track is not started");
   1544         return ERROR_END_OF_STREAM;
   1545     }
   1546 
   1547     if (mDone) {
   1548         return OK;
   1549     }
   1550     mDone = true;
   1551 
   1552     void *dummy;
   1553     pthread_join(mThread, &dummy);
   1554 
   1555     status_t err = (status_t) dummy;
   1556 
   1557     ALOGD("Stopping %s track source", mIsAudio? "Audio": "Video");
   1558     {
   1559         status_t status = mSource->stop();
   1560         if (err == OK && status != OK && status != ERROR_END_OF_STREAM) {
   1561             err = status;
   1562         }
   1563     }
   1564 
   1565     ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
   1566     return err;
   1567 }
   1568 
   1569 bool MPEG4Writer::Track::reachedEOS() {
   1570     return mReachedEOS;
   1571 }
   1572 
   1573 // static
   1574 void *MPEG4Writer::Track::ThreadWrapper(void *me) {
   1575     Track *track = static_cast<Track *>(me);
   1576 
   1577     status_t err = track->threadEntry();
   1578     return (void *) err;
   1579 }
   1580 
   1581 static void getNalUnitType(uint8_t byte, uint8_t* type) {
   1582     ALOGV("getNalUnitType: %d", byte);
   1583 
   1584     // nal_unit_type: 5-bit unsigned integer
   1585     *type = (byte & 0x1F);
   1586 }
   1587 
   1588 static const uint8_t *findNextStartCode(
   1589         const uint8_t *data, size_t length) {
   1590 
   1591     ALOGV("findNextStartCode: %p %d", data, length);
   1592 
   1593     size_t bytesLeft = length;
   1594     while (bytesLeft > 4  &&
   1595             memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
   1596         --bytesLeft;
   1597     }
   1598     if (bytesLeft <= 4) {
   1599         bytesLeft = 0; // Last parameter set
   1600     }
   1601     return &data[length - bytesLeft];
   1602 }
   1603 
   1604 const uint8_t *MPEG4Writer::Track::parseParamSet(
   1605         const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
   1606 
   1607     ALOGV("parseParamSet");
   1608     CHECK(type == kNalUnitTypeSeqParamSet ||
   1609           type == kNalUnitTypePicParamSet);
   1610 
   1611     const uint8_t *nextStartCode = findNextStartCode(data, length);
   1612     *paramSetLen = nextStartCode - data;
   1613     if (*paramSetLen == 0) {
   1614         ALOGE("Param set is malformed, since its length is 0");
   1615         return NULL;
   1616     }
   1617 
   1618     AVCParamSet paramSet(*paramSetLen, data);
   1619     if (type == kNalUnitTypeSeqParamSet) {
   1620         if (*paramSetLen < 4) {
   1621             ALOGE("Seq parameter set malformed");
   1622             return NULL;
   1623         }
   1624         if (mSeqParamSets.empty()) {
   1625             mProfileIdc = data[1];
   1626             mProfileCompatible = data[2];
   1627             mLevelIdc = data[3];
   1628         } else {
   1629             if (mProfileIdc != data[1] ||
   1630                 mProfileCompatible != data[2] ||
   1631                 mLevelIdc != data[3]) {
   1632                 ALOGE("Inconsistent profile/level found in seq parameter sets");
   1633                 return NULL;
   1634             }
   1635         }
   1636         mSeqParamSets.push_back(paramSet);
   1637     } else {
   1638         mPicParamSets.push_back(paramSet);
   1639     }
   1640     return nextStartCode;
   1641 }
   1642 
   1643 status_t MPEG4Writer::Track::copyAVCCodecSpecificData(
   1644         const uint8_t *data, size_t size) {
   1645     ALOGV("copyAVCCodecSpecificData");
   1646 
   1647     // 2 bytes for each of the parameter set length field
   1648     // plus the 7 bytes for the header
   1649     if (size < 4 + 7) {
   1650         ALOGE("Codec specific data length too short: %d", size);
   1651         return ERROR_MALFORMED;
   1652     }
   1653 
   1654     mCodecSpecificDataSize = size;
   1655     mCodecSpecificData = malloc(size);
   1656     memcpy(mCodecSpecificData, data, size);
   1657     return OK;
   1658 }
   1659 
   1660 status_t MPEG4Writer::Track::parseAVCCodecSpecificData(
   1661         const uint8_t *data, size_t size) {
   1662 
   1663     ALOGV("parseAVCCodecSpecificData");
   1664     // Data starts with a start code.
   1665     // SPS and PPS are separated with start codes.
   1666     // Also, SPS must come before PPS
   1667     uint8_t type = kNalUnitTypeSeqParamSet;
   1668     bool gotSps = false;
   1669     bool gotPps = false;
   1670     const uint8_t *tmp = data;
   1671     const uint8_t *nextStartCode = data;
   1672     size_t bytesLeft = size;
   1673     size_t paramSetLen = 0;
   1674     mCodecSpecificDataSize = 0;
   1675     while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
   1676         getNalUnitType(*(tmp + 4), &type);
   1677         if (type == kNalUnitTypeSeqParamSet) {
   1678             if (gotPps) {
   1679                 ALOGE("SPS must come before PPS");
   1680                 return ERROR_MALFORMED;
   1681             }
   1682             if (!gotSps) {
   1683                 gotSps = true;
   1684             }
   1685             nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
   1686         } else if (type == kNalUnitTypePicParamSet) {
   1687             if (!gotSps) {
   1688                 ALOGE("SPS must come before PPS");
   1689                 return ERROR_MALFORMED;
   1690             }
   1691             if (!gotPps) {
   1692                 gotPps = true;
   1693             }
   1694             nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
   1695         } else {
   1696             ALOGE("Only SPS and PPS Nal units are expected");
   1697             return ERROR_MALFORMED;
   1698         }
   1699 
   1700         if (nextStartCode == NULL) {
   1701             return ERROR_MALFORMED;
   1702         }
   1703 
   1704         // Move on to find the next parameter set
   1705         bytesLeft -= nextStartCode - tmp;
   1706         tmp = nextStartCode;
   1707         mCodecSpecificDataSize += (2 + paramSetLen);
   1708     }
   1709 
   1710     {
   1711         // Check on the number of seq parameter sets
   1712         size_t nSeqParamSets = mSeqParamSets.size();
   1713         if (nSeqParamSets == 0) {
   1714             ALOGE("Cound not find sequence parameter set");
   1715             return ERROR_MALFORMED;
   1716         }
   1717 
   1718         if (nSeqParamSets > 0x1F) {
   1719             ALOGE("Too many seq parameter sets (%d) found", nSeqParamSets);
   1720             return ERROR_MALFORMED;
   1721         }
   1722     }
   1723 
   1724     {
   1725         // Check on the number of pic parameter sets
   1726         size_t nPicParamSets = mPicParamSets.size();
   1727         if (nPicParamSets == 0) {
   1728             ALOGE("Cound not find picture parameter set");
   1729             return ERROR_MALFORMED;
   1730         }
   1731         if (nPicParamSets > 0xFF) {
   1732             ALOGE("Too many pic parameter sets (%d) found", nPicParamSets);
   1733             return ERROR_MALFORMED;
   1734         }
   1735     }
   1736 // FIXME:
   1737 // Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
   1738 // and remove #if 0
   1739 #if 0
   1740     {
   1741         // Check on the profiles
   1742         // These profiles requires additional parameter set extensions
   1743         if (mProfileIdc == 100 || mProfileIdc == 110 ||
   1744             mProfileIdc == 122 || mProfileIdc == 144) {
   1745             ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
   1746             return BAD_VALUE;
   1747         }
   1748     }
   1749 #endif
   1750     return OK;
   1751 }
   1752 
   1753 status_t MPEG4Writer::Track::makeAVCCodecSpecificData(
   1754         const uint8_t *data, size_t size) {
   1755 
   1756     if (mCodecSpecificData != NULL) {
   1757         ALOGE("Already have codec specific data");
   1758         return ERROR_MALFORMED;
   1759     }
   1760 
   1761     if (size < 4) {
   1762         ALOGE("Codec specific data length too short: %d", size);
   1763         return ERROR_MALFORMED;
   1764     }
   1765 
   1766     // Data is in the form of AVCCodecSpecificData
   1767     if (memcmp("\x00\x00\x00\x01", data, 4)) {
   1768         return copyAVCCodecSpecificData(data, size);
   1769     }
   1770 
   1771     if (parseAVCCodecSpecificData(data, size) != OK) {
   1772         return ERROR_MALFORMED;
   1773     }
   1774 
   1775     // ISO 14496-15: AVC file format
   1776     mCodecSpecificDataSize += 7;  // 7 more bytes in the header
   1777     mCodecSpecificData = malloc(mCodecSpecificDataSize);
   1778     uint8_t *header = (uint8_t *)mCodecSpecificData;
   1779     header[0] = 1;                     // version
   1780     header[1] = mProfileIdc;           // profile indication
   1781     header[2] = mProfileCompatible;    // profile compatibility
   1782     header[3] = mLevelIdc;
   1783 
   1784     // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
   1785     if (mOwner->useNalLengthFour()) {
   1786         header[4] = 0xfc | 3;  // length size == 4 bytes
   1787     } else {
   1788         header[4] = 0xfc | 1;  // length size == 2 bytes
   1789     }
   1790 
   1791     // 3-bit '111' followed by 5-bit numSequenceParameterSets
   1792     int nSequenceParamSets = mSeqParamSets.size();
   1793     header[5] = 0xe0 | nSequenceParamSets;
   1794     header += 6;
   1795     for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
   1796          it != mSeqParamSets.end(); ++it) {
   1797         // 16-bit sequence parameter set length
   1798         uint16_t seqParamSetLength = it->mLength;
   1799         header[0] = seqParamSetLength >> 8;
   1800         header[1] = seqParamSetLength & 0xff;
   1801 
   1802         // SPS NAL unit (sequence parameter length bytes)
   1803         memcpy(&header[2], it->mData, seqParamSetLength);
   1804         header += (2 + seqParamSetLength);
   1805     }
   1806 
   1807     // 8-bit nPictureParameterSets
   1808     int nPictureParamSets = mPicParamSets.size();
   1809     header[0] = nPictureParamSets;
   1810     header += 1;
   1811     for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
   1812          it != mPicParamSets.end(); ++it) {
   1813         // 16-bit picture parameter set length
   1814         uint16_t picParamSetLength = it->mLength;
   1815         header[0] = picParamSetLength >> 8;
   1816         header[1] = picParamSetLength & 0xff;
   1817 
   1818         // PPS Nal unit (picture parameter set length bytes)
   1819         memcpy(&header[2], it->mData, picParamSetLength);
   1820         header += (2 + picParamSetLength);
   1821     }
   1822 
   1823     return OK;
   1824 }
   1825 
   1826 /*
   1827  * Updates the drift time from the audio track so that
   1828  * the video track can get the updated drift time information
   1829  * from the file writer. The fluctuation of the drift time of the audio
   1830  * encoding path is smoothed out with a simple filter by giving a larger
   1831  * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
   1832  * are heuristically determined.
   1833  */
   1834 void MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
   1835     int64_t driftTimeUs = 0;
   1836     if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
   1837         int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
   1838         int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
   1839         mOwner->setDriftTimeUs(timeUs);
   1840     }
   1841 }
   1842 
   1843 status_t MPEG4Writer::Track::threadEntry() {
   1844     int32_t count = 0;
   1845     const int64_t interleaveDurationUs = mOwner->interleaveDuration();
   1846     const bool hasMultipleTracks = (mOwner->numTracks() > 1);
   1847     int64_t chunkTimestampUs = 0;
   1848     int32_t nChunks = 0;
   1849     int32_t nZeroLengthFrames = 0;
   1850     int64_t lastTimestampUs = 0;      // Previous sample time stamp
   1851     int64_t lastDurationUs = 0;       // Between the previous two samples
   1852     int64_t currDurationTicks = 0;    // Timescale based ticks
   1853     int64_t lastDurationTicks = 0;    // Timescale based ticks
   1854     int32_t sampleCount = 1;          // Sample count in the current stts table entry
   1855     uint32_t previousSampleSize = 0;  // Size of the previous sample
   1856     int64_t previousPausedDurationUs = 0;
   1857     int64_t timestampUs = 0;
   1858     int64_t cttsOffsetTimeUs = 0;
   1859     int64_t currCttsOffsetTimeTicks = 0;   // Timescale based ticks
   1860     int64_t lastCttsOffsetTimeTicks = -1;  // Timescale based ticks
   1861     int32_t cttsSampleCount = 0;           // Sample count in the current ctts table entry
   1862 
   1863     if (mIsAudio) {
   1864         prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
   1865     } else {
   1866         prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
   1867     }
   1868     androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
   1869 
   1870     sp<MetaData> meta_data;
   1871 
   1872     mNumSamples = 0;
   1873     status_t err = OK;
   1874     MediaBuffer *buffer;
   1875     while (!mDone && (err = mSource->read(&buffer)) == OK) {
   1876         if (buffer->range_length() == 0) {
   1877             buffer->release();
   1878             buffer = NULL;
   1879             ++nZeroLengthFrames;
   1880             continue;
   1881         }
   1882 
   1883         // If the codec specific data has not been received yet, delay pause.
   1884         // After the codec specific data is received, discard what we received
   1885         // when the track is to be paused.
   1886         if (mPaused && !mResumed) {
   1887             buffer->release();
   1888             buffer = NULL;
   1889             continue;
   1890         }
   1891 
   1892         ++count;
   1893 
   1894         int32_t isCodecConfig;
   1895         if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
   1896                 && isCodecConfig) {
   1897             CHECK(!mGotAllCodecSpecificData);
   1898 
   1899             if (mIsAvc) {
   1900                 status_t err = makeAVCCodecSpecificData(
   1901                         (const uint8_t *)buffer->data()
   1902                             + buffer->range_offset(),
   1903                         buffer->range_length());
   1904                 CHECK_EQ((status_t)OK, err);
   1905             } else if (mIsMPEG4) {
   1906                 mCodecSpecificDataSize = buffer->range_length();
   1907                 mCodecSpecificData = malloc(mCodecSpecificDataSize);
   1908                 memcpy(mCodecSpecificData,
   1909                         (const uint8_t *)buffer->data()
   1910                             + buffer->range_offset(),
   1911                        buffer->range_length());
   1912             }
   1913 
   1914             buffer->release();
   1915             buffer = NULL;
   1916 
   1917             mGotAllCodecSpecificData = true;
   1918             continue;
   1919         }
   1920 
   1921         // Make a deep copy of the MediaBuffer and Metadata and release
   1922         // the original as soon as we can
   1923         MediaBuffer *copy = new MediaBuffer(buffer->range_length());
   1924         memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
   1925                 buffer->range_length());
   1926         copy->set_range(0, buffer->range_length());
   1927         meta_data = new MetaData(*buffer->meta_data().get());
   1928         buffer->release();
   1929         buffer = NULL;
   1930 
   1931         if (mIsAvc) StripStartcode(copy);
   1932 
   1933         size_t sampleSize = copy->range_length();
   1934         if (mIsAvc) {
   1935             if (mOwner->useNalLengthFour()) {
   1936                 sampleSize += 4;
   1937             } else {
   1938                 sampleSize += 2;
   1939             }
   1940         }
   1941 
   1942         // Max file size or duration handling
   1943         mMdatSizeBytes += sampleSize;
   1944         updateTrackSizeEstimate();
   1945 
   1946         if (mOwner->exceedsFileSizeLimit()) {
   1947             mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
   1948             break;
   1949         }
   1950         if (mOwner->exceedsFileDurationLimit()) {
   1951             mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
   1952             break;
   1953         }
   1954 
   1955 
   1956         int32_t isSync = false;
   1957         meta_data->findInt32(kKeyIsSyncFrame, &isSync);
   1958         CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
   1959 
   1960 ////////////////////////////////////////////////////////////////////////////////
   1961         if (mNumSamples == 0) {
   1962             mFirstSampleTimeRealUs = systemTime() / 1000;
   1963             mStartTimestampUs = timestampUs;
   1964             mOwner->setStartTimestampUs(mStartTimestampUs);
   1965             previousPausedDurationUs = mStartTimestampUs;
   1966         }
   1967 
   1968         if (mResumed) {
   1969             int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
   1970             CHECK_GE(durExcludingEarlierPausesUs, 0ll);
   1971             int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
   1972             CHECK_GE(pausedDurationUs, lastDurationUs);
   1973             previousPausedDurationUs += pausedDurationUs - lastDurationUs;
   1974             mResumed = false;
   1975         }
   1976 
   1977         timestampUs -= previousPausedDurationUs;
   1978         CHECK_GE(timestampUs, 0ll);
   1979         if (!mIsAudio) {
   1980             /*
   1981              * Composition time: timestampUs
   1982              * Decoding time: decodingTimeUs
   1983              * Composition time offset = composition time - decoding time
   1984              */
   1985             int64_t decodingTimeUs;
   1986             CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
   1987             decodingTimeUs -= previousPausedDurationUs;
   1988             cttsOffsetTimeUs =
   1989                     timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
   1990             CHECK_GE(cttsOffsetTimeUs, 0ll);
   1991             timestampUs = decodingTimeUs;
   1992             ALOGV("decoding time: %lld and ctts offset time: %lld",
   1993                 timestampUs, cttsOffsetTimeUs);
   1994 
   1995             // Update ctts box table if necessary
   1996             currCttsOffsetTimeTicks =
   1997                     (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
   1998             CHECK_LE(currCttsOffsetTimeTicks, 0x0FFFFFFFFLL);
   1999             if (mNumSamples == 0) {
   2000                 // Force the first ctts table entry to have one single entry
   2001                 // so that we can do adjustment for the initial track start
   2002                 // time offset easily in writeCttsBox().
   2003                 lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
   2004                 addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
   2005                 cttsSampleCount = 0;      // No sample in ctts box is pending
   2006             } else {
   2007                 if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
   2008                     addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
   2009                     lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
   2010                     cttsSampleCount = 1;  // One sample in ctts box is pending
   2011                 } else {
   2012                     ++cttsSampleCount;
   2013                 }
   2014             }
   2015 
   2016             // Update ctts time offset range
   2017             if (mNumSamples == 0) {
   2018                 mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
   2019                 mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
   2020             } else {
   2021                 if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
   2022                     mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
   2023                 } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
   2024                     mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
   2025                 }
   2026             }
   2027 
   2028         }
   2029 
   2030         if (mIsRealTimeRecording) {
   2031             if (mIsAudio) {
   2032                 updateDriftTime(meta_data);
   2033             }
   2034         }
   2035 
   2036         CHECK_GE(timestampUs, 0ll);
   2037         ALOGV("%s media time stamp: %lld and previous paused duration %lld",
   2038                 mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs);
   2039         if (timestampUs > mTrackDurationUs) {
   2040             mTrackDurationUs = timestampUs;
   2041         }
   2042 
   2043         // We need to use the time scale based ticks, rather than the
   2044         // timestamp itself to determine whether we have to use a new
   2045         // stts entry, since we may have rounding errors.
   2046         // The calculation is intended to reduce the accumulated
   2047         // rounding errors.
   2048         currDurationTicks =
   2049             ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
   2050                 (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
   2051         CHECK_GE(currDurationTicks, 0ll);
   2052 
   2053         if ((mNumSamples % kSampleArraySize) == 0) {
   2054             uint32_t *arr = new uint32_t[kSampleArraySize];
   2055             CHECK(arr != NULL);
   2056             mSampleSizes.push_back(arr);
   2057             mCurrentSampleSizeArr = arr;
   2058         }
   2059 
   2060         mCurrentSampleSizeArr[mNumSamples % kSampleArraySize] = htonl(sampleSize);
   2061         ++mNumSamples;
   2062         if (mNumSamples > 2) {
   2063 
   2064             // Force the first sample to have its own stts entry so that
   2065             // we can adjust its value later to maintain the A/V sync.
   2066             if (mNumSamples == 3 || currDurationTicks != lastDurationTicks) {
   2067                 addOneSttsTableEntry(sampleCount, lastDurationTicks);
   2068                 sampleCount = 1;
   2069             } else {
   2070                 ++sampleCount;
   2071             }
   2072 
   2073         }
   2074         if (mSamplesHaveSameSize) {
   2075             if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
   2076                 mSamplesHaveSameSize = false;
   2077             }
   2078             previousSampleSize = sampleSize;
   2079         }
   2080         ALOGV("%s timestampUs/lastTimestampUs: %lld/%lld",
   2081                 mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs);
   2082         lastDurationUs = timestampUs - lastTimestampUs;
   2083         lastDurationTicks = currDurationTicks;
   2084         lastTimestampUs = timestampUs;
   2085 
   2086         if (isSync != 0) {
   2087             addOneStssTableEntry(mNumSamples);
   2088         }
   2089 
   2090         if (mTrackingProgressStatus) {
   2091             if (mPreviousTrackTimeUs <= 0) {
   2092                 mPreviousTrackTimeUs = mStartTimestampUs;
   2093             }
   2094             trackProgressStatus(timestampUs);
   2095         }
   2096         if (!hasMultipleTracks) {
   2097             off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
   2098                                  : mOwner->addSample_l(copy);
   2099             if (mChunkOffsets.empty()) {
   2100                 addChunkOffset(offset);
   2101             }
   2102             copy->release();
   2103             copy = NULL;
   2104             continue;
   2105         }
   2106 
   2107         mChunkSamples.push_back(copy);
   2108         if (interleaveDurationUs == 0) {
   2109             addOneStscTableEntry(++nChunks, 1);
   2110             bufferChunk(timestampUs);
   2111         } else {
   2112             if (chunkTimestampUs == 0) {
   2113                 chunkTimestampUs = timestampUs;
   2114             } else {
   2115                 int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
   2116                 if (chunkDurationUs > interleaveDurationUs) {
   2117                     if (chunkDurationUs > mMaxChunkDurationUs) {
   2118                         mMaxChunkDurationUs = chunkDurationUs;
   2119                     }
   2120                     ++nChunks;
   2121                     if (nChunks == 1 ||  // First chunk
   2122                         (--(mStscTableEntries.end()))->samplesPerChunk !=
   2123                          mChunkSamples.size()) {
   2124                         addOneStscTableEntry(nChunks, mChunkSamples.size());
   2125                     }
   2126                     bufferChunk(timestampUs);
   2127                     chunkTimestampUs = timestampUs;
   2128                 }
   2129             }
   2130         }
   2131 
   2132     }
   2133 
   2134     if (isTrackMalFormed()) {
   2135         err = ERROR_MALFORMED;
   2136     }
   2137 
   2138     mOwner->trackProgressStatus(mTrackId, -1, err);
   2139 
   2140     // Last chunk
   2141     if (!hasMultipleTracks) {
   2142         addOneStscTableEntry(1, mNumSamples);
   2143     } else if (!mChunkSamples.empty()) {
   2144         addOneStscTableEntry(++nChunks, mChunkSamples.size());
   2145         bufferChunk(timestampUs);
   2146     }
   2147 
   2148     // We don't really know how long the last frame lasts, since
   2149     // there is no frame time after it, just repeat the previous
   2150     // frame's duration.
   2151     if (mNumSamples == 1) {
   2152         lastDurationUs = 0;  // A single sample's duration
   2153         lastDurationTicks = 0;
   2154     } else {
   2155         ++sampleCount;  // Count for the last sample
   2156     }
   2157 
   2158     if (mNumSamples <= 2) {
   2159         addOneSttsTableEntry(1, lastDurationTicks);
   2160         if (sampleCount - 1 > 0) {
   2161             addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
   2162         }
   2163     } else {
   2164         addOneSttsTableEntry(sampleCount, lastDurationTicks);
   2165     }
   2166 
   2167     // The last ctts box may not have been written yet, and this
   2168     // is to make sure that we write out the last ctts box.
   2169     if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
   2170         if (cttsSampleCount > 0) {
   2171             addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
   2172         }
   2173     }
   2174 
   2175     mTrackDurationUs += lastDurationUs;
   2176     mReachedEOS = true;
   2177 
   2178     sendTrackSummary(hasMultipleTracks);
   2179 
   2180     ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
   2181             count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video");
   2182     if (mIsAudio) {
   2183         ALOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs());
   2184     }
   2185 
   2186     if (err == ERROR_END_OF_STREAM) {
   2187         return OK;
   2188     }
   2189     return err;
   2190 }
   2191 
   2192 bool MPEG4Writer::Track::isTrackMalFormed() const {
   2193     if (mSampleSizes.empty()) {                      // no samples written
   2194         ALOGE("The number of recorded samples is 0");
   2195         return true;
   2196     }
   2197 
   2198     if (!mIsAudio && mNumStssTableEntries == 0) {  // no sync frames for video
   2199         ALOGE("There are no sync frames for video track");
   2200         return true;
   2201     }
   2202 
   2203     if (OK != checkCodecSpecificData()) {         // no codec specific data
   2204         return true;
   2205     }
   2206 
   2207     return false;
   2208 }
   2209 
   2210 void MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
   2211 
   2212     // Send track summary only if test mode is enabled.
   2213     if (!isTestModeEnabled()) {
   2214         return;
   2215     }
   2216 
   2217     int trackNum = (mTrackId << 28);
   2218 
   2219     mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
   2220                     trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
   2221                     mIsAudio? 0: 1);
   2222 
   2223     mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
   2224                     trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
   2225                     mTrackDurationUs / 1000);
   2226 
   2227     mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
   2228                     trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
   2229                     mNumSamples);
   2230 
   2231     {
   2232         // The system delay time excluding the requested initial delay that
   2233         // is used to eliminate the recording sound.
   2234         int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
   2235         if (startTimeOffsetUs < 0) {  // Start time offset was not set
   2236             startTimeOffsetUs = kInitialDelayTimeUs;
   2237         }
   2238         int64_t initialDelayUs =
   2239             mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
   2240 
   2241         mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
   2242                     trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
   2243                     (initialDelayUs) / 1000);
   2244     }
   2245 
   2246     mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
   2247                     trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
   2248                     mMdatSizeBytes / 1024);
   2249 
   2250     if (hasMultipleTracks) {
   2251         mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
   2252                     trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
   2253                     mMaxChunkDurationUs / 1000);
   2254 
   2255         int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
   2256         if (mStartTimestampUs != moovStartTimeUs) {
   2257             int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
   2258             mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
   2259                     trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
   2260                     startTimeOffsetUs / 1000);
   2261         }
   2262     }
   2263 }
   2264 
   2265 void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
   2266     ALOGV("trackProgressStatus: %lld us", timeUs);
   2267     if (mTrackEveryTimeDurationUs > 0 &&
   2268         timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
   2269         ALOGV("Fire time tracking progress status at %lld us", timeUs);
   2270         mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
   2271         mPreviousTrackTimeUs = timeUs;
   2272     }
   2273 }
   2274 
   2275 void MPEG4Writer::trackProgressStatus(
   2276         size_t trackId, int64_t timeUs, status_t err) {
   2277     Mutex::Autolock lock(mLock);
   2278     int32_t trackNum = (trackId << 28);
   2279 
   2280     // Error notification
   2281     // Do not consider ERROR_END_OF_STREAM an error
   2282     if (err != OK && err != ERROR_END_OF_STREAM) {
   2283         notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
   2284                trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
   2285                err);
   2286         return;
   2287     }
   2288 
   2289     if (timeUs == -1) {
   2290         // Send completion notification
   2291         notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
   2292                trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
   2293                err);
   2294     } else {
   2295         // Send progress status
   2296         notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
   2297                trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
   2298                timeUs / 1000);
   2299     }
   2300 }
   2301 
   2302 void MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
   2303     ALOGV("setDriftTimeUs: %lld us", driftTimeUs);
   2304     Mutex::Autolock autolock(mLock);
   2305     mDriftTimeUs = driftTimeUs;
   2306 }
   2307 
   2308 int64_t MPEG4Writer::getDriftTimeUs() {
   2309     ALOGV("getDriftTimeUs: %lld us", mDriftTimeUs);
   2310     Mutex::Autolock autolock(mLock);
   2311     return mDriftTimeUs;
   2312 }
   2313 
   2314 bool MPEG4Writer::useNalLengthFour() {
   2315     return mUse4ByteNalLength;
   2316 }
   2317 
   2318 void MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
   2319     ALOGV("bufferChunk");
   2320 
   2321     Chunk chunk(this, timestampUs, mChunkSamples);
   2322     mOwner->bufferChunk(chunk);
   2323     mChunkSamples.clear();
   2324 }
   2325 
   2326 int64_t MPEG4Writer::Track::getDurationUs() const {
   2327     return mTrackDurationUs;
   2328 }
   2329 
   2330 int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
   2331     return mEstimatedTrackSizeBytes;
   2332 }
   2333 
   2334 status_t MPEG4Writer::Track::checkCodecSpecificData() const {
   2335     const char *mime;
   2336     CHECK(mMeta->findCString(kKeyMIMEType, &mime));
   2337     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
   2338         !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
   2339         !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
   2340         if (!mCodecSpecificData ||
   2341             mCodecSpecificDataSize <= 0) {
   2342             ALOGE("Missing codec specific data");
   2343             return ERROR_MALFORMED;
   2344         }
   2345     } else {
   2346         if (mCodecSpecificData ||
   2347             mCodecSpecificDataSize > 0) {
   2348             ALOGE("Unexepected codec specific data found");
   2349             return ERROR_MALFORMED;
   2350         }
   2351     }
   2352     return OK;
   2353 }
   2354 
   2355 void MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
   2356 
   2357     ALOGV("%s track time scale: %d",
   2358         mIsAudio? "Audio": "Video", mTimeScale);
   2359 
   2360     time_t now = time(NULL);
   2361     mOwner->beginBox("trak");
   2362         writeTkhdBox(now);
   2363         mOwner->beginBox("mdia");
   2364             writeMdhdBox(now);
   2365             writeHdlrBox();
   2366             mOwner->beginBox("minf");
   2367                 if (mIsAudio) {
   2368                     writeSmhdBox();
   2369                 } else {
   2370                     writeVmhdBox();
   2371                 }
   2372                 writeDinfBox();
   2373                 writeStblBox(use32BitOffset);
   2374             mOwner->endBox();  // minf
   2375         mOwner->endBox();  // mdia
   2376     mOwner->endBox();  // trak
   2377 }
   2378 
   2379 void MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
   2380     mOwner->beginBox("stbl");
   2381     mOwner->beginBox("stsd");
   2382     mOwner->writeInt32(0);               // version=0, flags=0
   2383     mOwner->writeInt32(1);               // entry count
   2384     if (mIsAudio) {
   2385         writeAudioFourCCBox();
   2386     } else {
   2387         writeVideoFourCCBox();
   2388     }
   2389     mOwner->endBox();  // stsd
   2390     writeSttsBox();
   2391     writeCttsBox();
   2392     if (!mIsAudio) {
   2393         writeStssBox();
   2394     }
   2395     writeStszBox();
   2396     writeStscBox();
   2397     writeStcoBox(use32BitOffset);
   2398     mOwner->endBox();  // stbl
   2399 }
   2400 
   2401 void MPEG4Writer::Track::writeVideoFourCCBox() {
   2402     const char *mime;
   2403     bool success = mMeta->findCString(kKeyMIMEType, &mime);
   2404     CHECK(success);
   2405     if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
   2406         mOwner->beginBox("mp4v");
   2407     } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
   2408         mOwner->beginBox("s263");
   2409     } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
   2410         mOwner->beginBox("avc1");
   2411     } else {
   2412         ALOGE("Unknown mime type '%s'.", mime);
   2413         CHECK(!"should not be here, unknown mime type.");
   2414     }
   2415 
   2416     mOwner->writeInt32(0);           // reserved
   2417     mOwner->writeInt16(0);           // reserved
   2418     mOwner->writeInt16(1);           // data ref index
   2419     mOwner->writeInt16(0);           // predefined
   2420     mOwner->writeInt16(0);           // reserved
   2421     mOwner->writeInt32(0);           // predefined
   2422     mOwner->writeInt32(0);           // predefined
   2423     mOwner->writeInt32(0);           // predefined
   2424 
   2425     int32_t width, height;
   2426     success = mMeta->findInt32(kKeyWidth, &width);
   2427     success = success && mMeta->findInt32(kKeyHeight, &height);
   2428     CHECK(success);
   2429 
   2430     mOwner->writeInt16(width);
   2431     mOwner->writeInt16(height);
   2432     mOwner->writeInt32(0x480000);    // horiz resolution
   2433     mOwner->writeInt32(0x480000);    // vert resolution
   2434     mOwner->writeInt32(0);           // reserved
   2435     mOwner->writeInt16(1);           // frame count
   2436     mOwner->write("                                ", 32);
   2437     mOwner->writeInt16(0x18);        // depth
   2438     mOwner->writeInt16(-1);          // predefined
   2439 
   2440     CHECK_LT(23 + mCodecSpecificDataSize, 128);
   2441 
   2442     if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
   2443         writeMp4vEsdsBox();
   2444     } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
   2445         writeD263Box();
   2446     } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
   2447         writeAvccBox();
   2448     }
   2449 
   2450     writePaspBox();
   2451     mOwner->endBox();  // mp4v, s263 or avc1
   2452 }
   2453 
   2454 void MPEG4Writer::Track::writeAudioFourCCBox() {
   2455     const char *mime;
   2456     bool success = mMeta->findCString(kKeyMIMEType, &mime);
   2457     CHECK(success);
   2458     const char *fourcc = NULL;
   2459     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
   2460         fourcc = "samr";
   2461     } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
   2462         fourcc = "sawb";
   2463     } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
   2464         fourcc = "mp4a";
   2465     } else {
   2466         ALOGE("Unknown mime type '%s'.", mime);
   2467         CHECK(!"should not be here, unknown mime type.");
   2468     }
   2469 
   2470     mOwner->beginBox(fourcc);        // audio format
   2471     mOwner->writeInt32(0);           // reserved
   2472     mOwner->writeInt16(0);           // reserved
   2473     mOwner->writeInt16(0x1);         // data ref index
   2474     mOwner->writeInt32(0);           // reserved
   2475     mOwner->writeInt32(0);           // reserved
   2476     int32_t nChannels;
   2477     CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
   2478     mOwner->writeInt16(nChannels);   // channel count
   2479     mOwner->writeInt16(16);          // sample size
   2480     mOwner->writeInt16(0);           // predefined
   2481     mOwner->writeInt16(0);           // reserved
   2482 
   2483     int32_t samplerate;
   2484     success = mMeta->findInt32(kKeySampleRate, &samplerate);
   2485     CHECK(success);
   2486     mOwner->writeInt32(samplerate << 16);
   2487     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
   2488         writeMp4aEsdsBox();
   2489     } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
   2490                !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
   2491         writeDamrBox();
   2492     }
   2493     mOwner->endBox();
   2494 }
   2495 
   2496 void MPEG4Writer::Track::writeMp4aEsdsBox() {
   2497     mOwner->beginBox("esds");
   2498     CHECK(mCodecSpecificData);
   2499     CHECK_GT(mCodecSpecificDataSize, 0);
   2500 
   2501     // Make sure all sizes encode to a single byte.
   2502     CHECK_LT(mCodecSpecificDataSize + 23, 128);
   2503 
   2504     mOwner->writeInt32(0);     // version=0, flags=0
   2505     mOwner->writeInt8(0x03);   // ES_DescrTag
   2506     mOwner->writeInt8(23 + mCodecSpecificDataSize);
   2507     mOwner->writeInt16(0x0000);// ES_ID
   2508     mOwner->writeInt8(0x00);
   2509 
   2510     mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
   2511     mOwner->writeInt8(15 + mCodecSpecificDataSize);
   2512     mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
   2513     mOwner->writeInt8(0x15);   // streamType AudioStream
   2514 
   2515     mOwner->writeInt16(0x03);  // XXX
   2516     mOwner->writeInt8(0x00);   // buffer size 24-bit
   2517     mOwner->writeInt32(96000); // max bit rate
   2518     mOwner->writeInt32(96000); // avg bit rate
   2519 
   2520     mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
   2521     mOwner->writeInt8(mCodecSpecificDataSize);
   2522     mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
   2523 
   2524     static const uint8_t kData2[] = {
   2525         0x06,  // SLConfigDescriptorTag
   2526         0x01,
   2527         0x02
   2528     };
   2529     mOwner->write(kData2, sizeof(kData2));
   2530 
   2531     mOwner->endBox();  // esds
   2532 }
   2533 
   2534 void MPEG4Writer::Track::writeMp4vEsdsBox() {
   2535     CHECK(mCodecSpecificData);
   2536     CHECK_GT(mCodecSpecificDataSize, 0);
   2537     mOwner->beginBox("esds");
   2538 
   2539     mOwner->writeInt32(0);    // version=0, flags=0
   2540 
   2541     mOwner->writeInt8(0x03);  // ES_DescrTag
   2542     mOwner->writeInt8(23 + mCodecSpecificDataSize);
   2543     mOwner->writeInt16(0x0000);  // ES_ID
   2544     mOwner->writeInt8(0x1f);
   2545 
   2546     mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
   2547     mOwner->writeInt8(15 + mCodecSpecificDataSize);
   2548     mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
   2549     mOwner->writeInt8(0x11);  // streamType VisualStream
   2550 
   2551     static const uint8_t kData[] = {
   2552         0x01, 0x77, 0x00,
   2553         0x00, 0x03, 0xe8, 0x00,
   2554         0x00, 0x03, 0xe8, 0x00
   2555     };
   2556     mOwner->write(kData, sizeof(kData));
   2557 
   2558     mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
   2559 
   2560     mOwner->writeInt8(mCodecSpecificDataSize);
   2561     mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
   2562 
   2563     static const uint8_t kData2[] = {
   2564         0x06,  // SLConfigDescriptorTag
   2565         0x01,
   2566         0x02
   2567     };
   2568     mOwner->write(kData2, sizeof(kData2));
   2569 
   2570     mOwner->endBox();  // esds
   2571 }
   2572 
   2573 void MPEG4Writer::Track::writeTkhdBox(time_t now) {
   2574     mOwner->beginBox("tkhd");
   2575     // Flags = 7 to indicate that the track is enabled, and
   2576     // part of the presentation
   2577     mOwner->writeInt32(0x07);          // version=0, flags=7
   2578     mOwner->writeInt32(now);           // creation time
   2579     mOwner->writeInt32(now);           // modification time
   2580     mOwner->writeInt32(mTrackId + 1);  // track id starts with 1
   2581     mOwner->writeInt32(0);             // reserved
   2582     int64_t trakDurationUs = getDurationUs();
   2583     int32_t mvhdTimeScale = mOwner->getTimeScale();
   2584     int32_t tkhdDuration =
   2585         (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
   2586     mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
   2587     mOwner->writeInt32(0);             // reserved
   2588     mOwner->writeInt32(0);             // reserved
   2589     mOwner->writeInt16(0);             // layer
   2590     mOwner->writeInt16(0);             // alternate group
   2591     mOwner->writeInt16(mIsAudio ? 0x100 : 0);  // volume
   2592     mOwner->writeInt16(0);             // reserved
   2593 
   2594     mOwner->writeCompositionMatrix(mRotation);       // matrix
   2595 
   2596     if (mIsAudio) {
   2597         mOwner->writeInt32(0);
   2598         mOwner->writeInt32(0);
   2599     } else {
   2600         int32_t width, height;
   2601         bool success = mMeta->findInt32(kKeyWidth, &width);
   2602         success = success && mMeta->findInt32(kKeyHeight, &height);
   2603         CHECK(success);
   2604 
   2605         mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
   2606         mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
   2607     }
   2608     mOwner->endBox();  // tkhd
   2609 }
   2610 
   2611 void MPEG4Writer::Track::writeVmhdBox() {
   2612     mOwner->beginBox("vmhd");
   2613     mOwner->writeInt32(0x01);        // version=0, flags=1
   2614     mOwner->writeInt16(0);           // graphics mode
   2615     mOwner->writeInt16(0);           // opcolor
   2616     mOwner->writeInt16(0);
   2617     mOwner->writeInt16(0);
   2618     mOwner->endBox();
   2619 }
   2620 
   2621 void MPEG4Writer::Track::writeSmhdBox() {
   2622     mOwner->beginBox("smhd");
   2623     mOwner->writeInt32(0);           // version=0, flags=0
   2624     mOwner->writeInt16(0);           // balance
   2625     mOwner->writeInt16(0);           // reserved
   2626     mOwner->endBox();
   2627 }
   2628 
   2629 void MPEG4Writer::Track::writeHdlrBox() {
   2630     mOwner->beginBox("hdlr");
   2631     mOwner->writeInt32(0);             // version=0, flags=0
   2632     mOwner->writeInt32(0);             // component type: should be mhlr
   2633     mOwner->writeFourcc(mIsAudio ? "soun" : "vide");  // component subtype
   2634     mOwner->writeInt32(0);             // reserved
   2635     mOwner->writeInt32(0);             // reserved
   2636     mOwner->writeInt32(0);             // reserved
   2637     // Removing "r" for the name string just makes the string 4 byte aligned
   2638     mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle");  // name
   2639     mOwner->endBox();
   2640 }
   2641 
   2642 void MPEG4Writer::Track::writeMdhdBox(time_t now) {
   2643     int64_t trakDurationUs = getDurationUs();
   2644     mOwner->beginBox("mdhd");
   2645     mOwner->writeInt32(0);             // version=0, flags=0
   2646     mOwner->writeInt32(now);           // creation time
   2647     mOwner->writeInt32(now);           // modification time
   2648     mOwner->writeInt32(mTimeScale);    // media timescale
   2649     int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
   2650     mOwner->writeInt32(mdhdDuration);  // use media timescale
   2651     // Language follows the three letter standard ISO-639-2/T
   2652     // 'e', 'n', 'g' for "English", for instance.
   2653     // Each character is packed as the difference between its ASCII value and 0x60.
   2654     // For "English", these are 00101, 01110, 00111.
   2655     // XXX: Where is the padding bit located: 0x15C7?
   2656     mOwner->writeInt16(0);             // language code
   2657     mOwner->writeInt16(0);             // predefined
   2658     mOwner->endBox();
   2659 }
   2660 
   2661 void MPEG4Writer::Track::writeDamrBox() {
   2662     // 3gpp2 Spec AMRSampleEntry fields
   2663     mOwner->beginBox("damr");
   2664     mOwner->writeCString("   ");  // vendor: 4 bytes
   2665     mOwner->writeInt8(0);         // decoder version
   2666     mOwner->writeInt16(0x83FF);   // mode set: all enabled
   2667     mOwner->writeInt8(0);         // mode change period
   2668     mOwner->writeInt8(1);         // frames per sample
   2669     mOwner->endBox();
   2670 }
   2671 
   2672 void MPEG4Writer::Track::writeUrlBox() {
   2673     // The table index here refers to the sample description index
   2674     // in the sample table entries.
   2675     mOwner->beginBox("url ");
   2676     mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
   2677     mOwner->endBox();  // url
   2678 }
   2679 
   2680 void MPEG4Writer::Track::writeDrefBox() {
   2681     mOwner->beginBox("dref");
   2682     mOwner->writeInt32(0);  // version=0, flags=0
   2683     mOwner->writeInt32(1);  // entry count (either url or urn)
   2684     writeUrlBox();
   2685     mOwner->endBox();  // dref
   2686 }
   2687 
   2688 void MPEG4Writer::Track::writeDinfBox() {
   2689     mOwner->beginBox("dinf");
   2690     writeDrefBox();
   2691     mOwner->endBox();  // dinf
   2692 }
   2693 
   2694 void MPEG4Writer::Track::writeAvccBox() {
   2695     CHECK(mCodecSpecificData);
   2696     CHECK_GE(mCodecSpecificDataSize, 5);
   2697 
   2698     // Patch avcc's lengthSize field to match the number
   2699     // of bytes we use to indicate the size of a nal unit.
   2700     uint8_t *ptr = (uint8_t *)mCodecSpecificData;
   2701     ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
   2702     mOwner->beginBox("avcC");
   2703     mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
   2704     mOwner->endBox();  // avcC
   2705 }
   2706 
   2707 void MPEG4Writer::Track::writeD263Box() {
   2708     mOwner->beginBox("d263");
   2709     mOwner->writeInt32(0);  // vendor
   2710     mOwner->writeInt8(0);   // decoder version
   2711     mOwner->writeInt8(10);  // level: 10
   2712     mOwner->writeInt8(0);   // profile: 0
   2713     mOwner->endBox();  // d263
   2714 }
   2715 
   2716 // This is useful if the pixel is not square
   2717 void MPEG4Writer::Track::writePaspBox() {
   2718     mOwner->beginBox("pasp");
   2719     mOwner->writeInt32(1 << 16);  // hspacing
   2720     mOwner->writeInt32(1 << 16);  // vspacing
   2721     mOwner->endBox();  // pasp
   2722 }
   2723 
   2724 int32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
   2725     int64_t trackStartTimeOffsetUs = 0;
   2726     int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
   2727     if (mStartTimestampUs != moovStartTimeUs) {
   2728         CHECK_GT(mStartTimestampUs, moovStartTimeUs);
   2729         trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
   2730     }
   2731     return (trackStartTimeOffsetUs *  mTimeScale + 500000LL) / 1000000LL;
   2732 }
   2733 
   2734 void MPEG4Writer::Track::writeSttsBox() {
   2735     mOwner->beginBox("stts");
   2736     mOwner->writeInt32(0);  // version=0, flags=0
   2737     mOwner->writeInt32(mNumSttsTableEntries);
   2738 
   2739     // Compensate for small start time difference from different media tracks
   2740     List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
   2741     CHECK(it != mSttsTableEntries.end() && it->sampleCount == 1);
   2742     mOwner->writeInt32(it->sampleCount);
   2743     mOwner->writeInt32(getStartTimeOffsetScaledTime() + it->sampleDuration);
   2744 
   2745     int64_t totalCount = 1;
   2746     while (++it != mSttsTableEntries.end()) {
   2747         mOwner->writeInt32(it->sampleCount);
   2748         mOwner->writeInt32(it->sampleDuration);
   2749         totalCount += it->sampleCount;
   2750     }
   2751     CHECK_EQ(totalCount, mNumSamples);
   2752     mOwner->endBox();  // stts
   2753 }
   2754 
   2755 void MPEG4Writer::Track::writeCttsBox() {
   2756     if (mIsAudio) {  // ctts is not for audio
   2757         return;
   2758     }
   2759 
   2760     // There is no B frame at all
   2761     if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
   2762         return;
   2763     }
   2764 
   2765     // Do not write ctts box when there is no need to have it.
   2766     if ((mNumCttsTableEntries == 1 &&
   2767         mCttsTableEntries.begin()->sampleDuration == 0) ||
   2768         mNumCttsTableEntries == 0) {
   2769         return;
   2770     }
   2771 
   2772     ALOGD("ctts box has %d entries with range [%lld, %lld]",
   2773             mNumCttsTableEntries, mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
   2774 
   2775     mOwner->beginBox("ctts");
   2776     // Version 1 allows to use negative offset time value, but
   2777     // we are sticking to version 0 for now.
   2778     mOwner->writeInt32(0);  // version=0, flags=0
   2779     mOwner->writeInt32(mNumCttsTableEntries);
   2780 
   2781     // Compensate for small start time difference from different media tracks
   2782     List<CttsTableEntry>::iterator it = mCttsTableEntries.begin();
   2783     CHECK(it != mCttsTableEntries.end() && it->sampleCount == 1);
   2784     mOwner->writeInt32(it->sampleCount);
   2785     mOwner->writeInt32(getStartTimeOffsetScaledTime() +
   2786             it->sampleDuration - mMinCttsOffsetTimeUs);
   2787 
   2788     int64_t totalCount = 1;
   2789     while (++it != mCttsTableEntries.end()) {
   2790         mOwner->writeInt32(it->sampleCount);
   2791         mOwner->writeInt32(it->sampleDuration - mMinCttsOffsetTimeUs);
   2792         totalCount += it->sampleCount;
   2793     }
   2794     CHECK_EQ(totalCount, mNumSamples);
   2795     mOwner->endBox();  // ctts
   2796 }
   2797 
   2798 void MPEG4Writer::Track::writeStssBox() {
   2799     mOwner->beginBox("stss");
   2800     mOwner->writeInt32(0);  // version=0, flags=0
   2801     mOwner->writeInt32(mNumStssTableEntries);  // number of sync frames
   2802     for (List<int32_t>::iterator it = mStssTableEntries.begin();
   2803         it != mStssTableEntries.end(); ++it) {
   2804         mOwner->writeInt32(*it);
   2805     }
   2806     mOwner->endBox();  // stss
   2807 }
   2808 
   2809 void MPEG4Writer::Track::writeStszBox() {
   2810     ALOGD("writeStszBox for %s track", isAudio()? "Audio": "Video");
   2811     mOwner->beginBox("stsz");
   2812     mOwner->writeInt32(0);  // version=0, flags=0
   2813     if (mSamplesHaveSameSize) {
   2814         CHECK(mCurrentSampleSizeArr != 0);
   2815         mOwner->write(mCurrentSampleSizeArr, 4, 1);  // default sample size
   2816     } else {
   2817         mOwner->writeInt32(0);
   2818     }
   2819     mOwner->writeInt32(mNumSamples);
   2820     uint32_t nSamples = mNumSamples;
   2821     if (!mSamplesHaveSameSize) {
   2822         for (List<uint32_t *>::iterator it = mSampleSizes.begin();
   2823             it != mSampleSizes.end(); ++it) {
   2824             if (nSamples >= kSampleArraySize) {
   2825                 mOwner->write(*it, 4, kSampleArraySize);
   2826                 nSamples -= kSampleArraySize;
   2827             } else {
   2828                 mOwner->write(*it, 4, nSamples);
   2829                 break;
   2830             }
   2831         }
   2832     }
   2833     mOwner->endBox();  // stsz
   2834     ALOGD("writeStszBox: X");
   2835 }
   2836 
   2837 void MPEG4Writer::Track::writeStscBox() {
   2838     mOwner->beginBox("stsc");
   2839     mOwner->writeInt32(0);  // version=0, flags=0
   2840     mOwner->writeInt32(mNumStscTableEntries);
   2841     for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
   2842         it != mStscTableEntries.end(); ++it) {
   2843         mOwner->writeInt32(it->firstChunk);
   2844         mOwner->writeInt32(it->samplesPerChunk);
   2845         mOwner->writeInt32(it->sampleDescriptionId);
   2846     }
   2847     mOwner->endBox();  // stsc
   2848 }
   2849 
   2850 void MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
   2851     mOwner->beginBox(use32BitOffset? "stco": "co64");
   2852     mOwner->writeInt32(0);  // version=0, flags=0
   2853     mOwner->writeInt32(mNumStcoTableEntries);
   2854     for (List<off64_t>::iterator it = mChunkOffsets.begin();
   2855         it != mChunkOffsets.end(); ++it) {
   2856         if (use32BitOffset) {
   2857             mOwner->writeInt32(static_cast<int32_t>(*it));
   2858         } else {
   2859             mOwner->writeInt64((*it));
   2860         }
   2861     }
   2862     mOwner->endBox();  // stco or co64
   2863 }
   2864 
   2865 void MPEG4Writer::writeUdtaBox() {
   2866     beginBox("udta");
   2867     writeGeoDataBox();
   2868     endBox();
   2869 }
   2870 
   2871 /*
   2872  * Geodata is stored according to ISO-6709 standard.
   2873  */
   2874 void MPEG4Writer::writeGeoDataBox() {
   2875     beginBox("\xA9xyz");
   2876     /*
   2877      * For historical reasons, any user data start
   2878      * with "\0xA9", must be followed by its assoicated
   2879      * language code.
   2880      * 0x0012: text string length
   2881      * 0x15c7: lang (locale) code: en
   2882      */
   2883     writeInt32(0x001215c7);
   2884     writeLatitude(mLatitudex10000);
   2885     writeLongitude(mLongitudex10000);
   2886     writeInt8(0x2F);
   2887     endBox();
   2888 }
   2889 
   2890 }  // namespace android
   2891