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