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