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