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