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